Below is a bash script to move files around and rename them. The problem is it doesn't work when there is more than one file in the directory. I'm assuming because the last parameter in the mv command is a file. Any suggestions?
'#!/bin/bash'
'INPUTDIR="/home/southern-uniontn/S001007420"'
'OUTPUTDIR="/mnt/edi-06/southern-uniontn/flats-in"'
'BACKUPDIR="/backup/southern-uniontn/S001007420"'
YEAR=`date %Y`
MONTH=`date %m`
DAY=`date %d`
HOUR=`date %H`
MINUTE=`date %M`
######## Do some error checking #########
# Does backup dir exist?
if [ ! -d $BACKUPDIR/$YEAR ]
then
mkdir $BACKUPDIR/$YEAR
fi
if [ ! -d $BACKUPDIR/$YEAR/$MONTH ]
then
mkdir $BACKUPDIR/$YEAR/$MONTH
fi
if [ ! -d $BACKUPDIR/$YEAR/$MONTH/$DAY ]
then
mkdir $BACKUPDIR/$YEAR/$MONTH/$DAY
fi
if [[ $(find $INPUTDIR -type f | wc -l) -gt 0 ]];
then
###### Rename the file, move it to Backup, then copy to the Output Directory #####
for f in $INPUTDIR/*
do
echo "`date` - Move recurring txt flat file to BackupDir for Union TN from Southern"
mv $INPUTDIR/* $BACKUPDIR/$YEAR/$MONTH/$DAY/UnionTN-S001007420-$YEAR$MONTH$DAY-$HOUR$MINUTE.txt
sleep 2
echo "`date` - Copy backup file to the Union TN Output Directory"
cp $BACKUPDIR/$YEAR/$MONTH/$DAY/UnionTN-S001007420-$YEAR$MONTH$DAY-$HOUR$MINUTE.txt $OUTPUTDIR/
done;
fi
CodePudding user response:
Some notes:
Get out of the habit of using ALLCAPS variable names, leave those as reserved by the shell. One day you'll write
PATH=something
and then wonder why your script is broken.mkdir -p
can create parent directories, and will not error if the dir already existsstore the filenames in an array. Then the shell does not have to duplicate the work, and you don't need to count how many there are: if there are no files, the loop has zero iterations
if you want to keep the same directory hierarchy in the outputdir, you need to do that by hand.
use
read
to get the date partswith bash v4.2 ,
printf
can be used instead of calling out todate
- use magic value "-1" to mean "now".
printf '%(%Y-%m-%d)T\n' -1
prints "2021-10-25" (as of the day I write this)
This is, I think, what you want:
#!/bin/bash
inputdir='/home/southern-uniontn/S001007420'
outputdir='/mnt/edi-06/southern-uniontn/flats-in'
backupdir='/backup/southern-uniontn/S001007420'
read year month day hour minute < <(printf '%(%Y %m %d %H %M)T\n' -1)
# create backup dirs if not exists
date_dir="$year/$month/$day"
mkdir -p "$backupdir/$date_dir"
mkdir -p "$outputdir/$date_dir"
mapfile -t files < <(find $inputdir -type f)
for f in "${files[@]}"
do
###### Rename the file, move it to Backup, then copy to the Output Directory #####
backup_file="UnionTN-S001007420-$year$month$day-$hour$minute.txt"
printf '%(%c)T - Move recurring txt flat file to backupdir for Union TN from Southern\n' -1
mv "$f" "$backupdir/$date_dir/$backup_file"
printf '%(%c)T - Copy backup file to the Union TN Output Directory\n' -1
cp "$backupdir/$date_dir/$backup_file" "$outputdir/$date_dir/$backup_file"
done
CodePudding user response:
When using a glob with mv
, the target must be an existing directory, and all matching files will be moved inside that directory.
In your case,
mv $INPUTDIR/* $BACKUPDIR/$YEAR/$MONTH/$DAY/UnionTN-S001007420-$YEAR$MONTH$DAY-$HOUR$MINUTE.txt
tells mv
to move all file inside the $INPUTDIR/*
directory to a directory named $BACKUPDIR/$YEAR/$MONTH/$DAY/UnionTN-S001007420-$YEAR$MONTH$DAY-$HOUR$MINUTE.txt
.
I'm not sure what you're trying to do, but I hope this help.
Some more advice you could use:
- you don't have to put the shebang (the first line beginning with "#") and the first three variable declarations inside single-quotes.
- Some argue it is more portable and better to write
/usr/bin/env bash
instead of/bin/bash
in the shebang if [ CONDITION ] /then ACTION /fi
statements can be simplified by writing[ CONDITION ] && ACTION
- You reduce your likely hood of encountering unexpected behaviour when using string interpolation (i.e. write
"${year}/${month}/"
instead of${year}/${month}
. - No need to call
mkdir a
, followed bymkidr a/b
, thenmkdir a/b/c
and so on, you can just callmkdir -p a/b/c
. Thep
flag tellsmkdir
to create parent directories if they don't already exist. - It is unnecessary to validate the existence of a directory before calling
mkdir
sincemkdir
already validates that for you. - As pointed out by commenters, all-caps variables are conventions for special POSIX related variables. You should use another type of casing.
- You could use
date
to do the formatting for you:date %Y/%m/%d
will print2021/10/25
- Strings without interpolation can have single-quotes.
- (Optional, prevent undesired behaviors) Put
set -e
at the beginning of your scripts, after the shebang, to tell bash to halt if an error is encountered - And finally, use
man <command_name>
for built-in documentation!