patternbashMinor
Bash archiving script
Viewed 0 times
scriptarchivingbash
Problem
I inherited a script at work the other day. I know very little about the command line in general but I'm not entirely new to programming. I am using this as an opportunity to learn... Very little of the original code is left (so if it's all wrong, it's my fault now). I was asked to modify it retain sub-directories so I chose to use
The directories being archived are huge; maybe not crazy huge but definitely big. It should be ran often enough where there aren't too many files to process. Hopefully. I'm not sure how concerned I should be about that yet. It can be assumed that more than once instance of this script will never be running at the same time.
```
function archive() {
log_dir=$1 # /home/u123/initial_files/SessLogs
age=$2 # age of the files to process
archive=$3 # base of the archive directory
exclude=$4 # exclude_list of directories/files
base_dir=${log_dir%/*} # /home/u123/initial_files
ftype=${log_dir##*/} # SessLogs
date_dir=$(make_date_string $age)
# make the new folder in the archive with the date
arch_dir=$archive/$ftype/$date_dir
[ ! -d $archive/$ftype ] && ( mkdir $archive/$ftype )
[ ! -d $arch_dir ] && ( mkdir $arch_dir )
outfile=$arch_dir/archivelog.txt
printf "$(date)""\n\n" >>$outfile
printf "%s\n" "processing $ftype files..." >>$outfile
printf "%s\n" " - type = $ftype" >>$outfile
printf "%s\n" " - age = $age days" >>$outfile
printf "%s\n" " - log_dir = $log_dir" >>$outfile
printf "%s\n" " - archive = $archive" >>$outfile
printf "%s\n" " - exclude = $exclude" >>$outfile
printf "\n">>$outfile
# test for valid age
if [ $age -lt 1 ]; then
printf "\n%s\n" "age parameter is invalid" >>$outfile
return 0
# test for existence of log file
elif [ ! -d $log_dir ]; then
printf "\n%s\n" "log directory cannot be found $log_dir" >>$outfile
return 0
# test for existence of excl
tar.The directories being archived are huge; maybe not crazy huge but definitely big. It should be ran often enough where there aren't too many files to process. Hopefully. I'm not sure how concerned I should be about that yet. It can be assumed that more than once instance of this script will never be running at the same time.
```
function archive() {
log_dir=$1 # /home/u123/initial_files/SessLogs
age=$2 # age of the files to process
archive=$3 # base of the archive directory
exclude=$4 # exclude_list of directories/files
base_dir=${log_dir%/*} # /home/u123/initial_files
ftype=${log_dir##*/} # SessLogs
date_dir=$(make_date_string $age)
# make the new folder in the archive with the date
arch_dir=$archive/$ftype/$date_dir
[ ! -d $archive/$ftype ] && ( mkdir $archive/$ftype )
[ ! -d $arch_dir ] && ( mkdir $arch_dir )
outfile=$arch_dir/archivelog.txt
printf "$(date)""\n\n" >>$outfile
printf "%s\n" "processing $ftype files..." >>$outfile
printf "%s\n" " - type = $ftype" >>$outfile
printf "%s\n" " - age = $age days" >>$outfile
printf "%s\n" " - log_dir = $log_dir" >>$outfile
printf "%s\n" " - archive = $archive" >>$outfile
printf "%s\n" " - exclude = $exclude" >>$outfile
printf "\n">>$outfile
# test for valid age
if [ $age -lt 1 ]; then
printf "\n%s\n" "age parameter is invalid" >>$outfile
return 0
# test for existence of log file
elif [ ! -d $log_dir ]; then
printf "\n%s\n" "log directory cannot be found $log_dir" >>$outfile
return 0
# test for existence of excl
Solution
You can simplify this:
to this:
That is:
First of all, unless you have a good reason, don't use a
Secondly, if a simple
Redirecting many lines to
A better way would be:
As mentioned earlier, an even better way would be rewriting these with simple
Finally, since you have many lines appending to
it might be best to create a helper function for it.
When using
You also don't need to quote barewords like "0". So this is enough:
This probably doesn't do what you expect:
and I'm guessing that you're in fact really interested in the
If you want to act on the exit code of the
And no need to quote
Copy-paste your code to http://www.shellcheck.net/# and it will point out a couple of more things that you should fix.
arch_dir=$archive/$ftype/$date_dir
[ ! -d $archive/$ftype ] && ( mkdir $archive/$ftype )
[ ! -d $arch_dir ] && ( mkdir $arch_dir )to this:
[ -d $arch_dir ] || mkdir -p $arch_dirThat is:
- The
-pflag ofmkdirwill make it create all intermediary directories as necessary
- No need to put
(...)around themkdir
- Using
... ||instead of! ... &&is shorter, and perhaps even more natural too
printf "$(date)""\n\n" >>$outfileFirst of all, unless you have a good reason, don't use a
$(...) subshell to capture the output of a command just to print it. Use the output directly:date >>$outfileSecondly, if a simple
echo without parameters is enough, I would use that instead of a printf. If you need any of the flags of echo, then it's better to use printf, as it's more portable. For printing a blank line, I'd use echo.Redirecting many lines to
$outfile like this feels a bit repetitive:printf "%s\n" "processing $ftype files..." >>$outfile
printf "%s\n" " - type = $ftype" >>$outfile
printf "%s\n" " - age = $age days" >>$outfile
printf "%s\n" " - log_dir = $log_dir" >>$outfile
printf "%s\n" " - archive = $archive" >>$outfile
printf "%s\n" " - exclude = $exclude" >>$outfile
printf "\n">>$outfileA better way would be:
{
printf "%s\n" "processing $ftype files..."
printf "%s\n" " - type = $ftype"
printf "%s\n" " - age = $age days"
printf "%s\n" " - log_dir = $log_dir"
printf "%s\n" " - archive = $archive"
printf "%s\n" " - exclude = $exclude"
printf "\n"
} >> $outfileAs mentioned earlier, an even better way would be rewriting these with simple
echo, for example:echo "processing $ftype files..."Finally, since you have many lines appending to
$outfile,it might be best to create a helper function for it.
if [[ "$files" -eq "0" ]] ; thenWhen using
[[ ... ]], you don't need to quote variables on the left side.You also don't need to quote barewords like "0". So this is enough:
if [[ $files == 0 ]] ; thenThis probably doesn't do what you expect:
tar xvp -C "$arch_dir" -f "$arch_dir"/archive.tar --strip-components="$sc" 1>&2>>$outfile
printf "\n\n" >>$outfile
# if no error: rm "$arch_dir"/archive.tar
if [ "$?" = "0" ]; then$? is the exit code of the last command. In this case the printf,and I'm guessing that you're in fact really interested in the
tar instead.If you want to act on the exit code of the
tar, then you can either use the || operator right after it, or save the exit code, for example:tar xvp -C "$arch_dir" -f "$arch_dir"/archive.tar --strip-components="$sc" 1>&2>>$outfile
tar_exit=$?
printf "\n\n" >>$outfile
# if no error: rm "$arch_dir"/archive.tar
if [ $tar_exit = 0 ]; thenAnd no need to quote
$? as it's always a number, never blank, never contains spaces.Copy-paste your code to http://www.shellcheck.net/# and it will point out a couple of more things that you should fix.
Code Snippets
arch_dir=$archive/$ftype/$date_dir
[ ! -d $archive/$ftype ] && ( mkdir $archive/$ftype )
[ ! -d $arch_dir ] && ( mkdir $arch_dir )[ -d $arch_dir ] || mkdir -p $arch_dirprintf "$(date)""\n\n" >>$outfiledate >>$outfileprintf "%s\n" "processing $ftype files..." >>$outfile
printf "%s\n" " - type = $ftype" >>$outfile
printf "%s\n" " - age = $age days" >>$outfile
printf "%s\n" " - log_dir = $log_dir" >>$outfile
printf "%s\n" " - archive = $archive" >>$outfile
printf "%s\n" " - exclude = $exclude" >>$outfile
printf "\n">>$outfileContext
StackExchange Code Review Q#67956, answer score: 2
Revisions (0)
No revisions yet.