Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unix for loop skipping one value in script, works properly in command line

Tags:

shell

unix

ksh

I am running the following commands in command line:

for DATAFILE in `find dir_name -type f -mtime +10 | egrep -v -e 'archive/'`
do
    echo 'Data file name- ' "$DATAFILE"
    echo 'Base name ' 
    BASENAME=`basename "${DATAFILE}"`
    DESTFILE="${BASENAME}"_`date +"%Y%m%d%H%M%S"`
    echo "Dest file - "$DESTFILE
done

I get the following result for this:

Data file name-  DIR_PATH_1/file_1.txt
Base name
Dest file - file_1.txt_20120719041239
Data file name-  DIR_PATH_2/file_2.txt
Base name
Dest file - file_2.txt_20120719041239

When I put the same commands in a shell script and execute, I get the following result:

Data file name-  DIR_PATH_1/file_1.txt
DIR_PATH_2/file_2.txt
Base name
Dest file - file_2.txt_20120719040956

I have checked the script for Control-M and other junk characters. Also, I don't have any extra steps in the shell script (no parameters and all).

Can someone point me in the right direction.

Thanks.

Update 1:

I made the following change to the loop:

Earlier:

for DATAFILE in `find ${ROOT_DIR} -type f -mtime +$DAYS_ARCH | 
                     egrep -v -e 'archive/'`

Now:

find ${ROOT_DIR} -type f -mtime +$DAYS_ARCH |
     egrep -v -e 'archive/' | while read DATAFILE

It seems to be working properly now. I am still testing to confirm this.

Update 2:

Changing from FOR to WHILE loop has fixed the issue. But still I am not able to understand why this is happening. Anyone?

like image 397
visakh Avatar asked Dec 01 '25 02:12

visakh


2 Answers

Capturing find output in backticks will effectively join all lines. This will break file names with embedded spaces.

for DATAFILE in find ${ROOT_DIR} -type f -mtime +$DAYS_ARCH | egrep -v -e 'archive/'

The while read ... loop will read exactly one pathname at a time, even if they contain white space or other special characters.

like image 127
Henk Langeveld Avatar answered Dec 04 '25 13:12

Henk Langeveld


Add to your script:

echo "My shell is: " $0
echo "My IFS is:" $IFS

and compare it with results from interactive shell.

Make sure your script is executed by script you want, by adding a hashbang line.

According to man sh, IFS is defined as:

Input Field Separators. This is normally set to ⟨space⟩, ⟨tab⟩, and ⟨newline⟩. See the White Space Splitting section for more details.

like image 40
Michał Šrajer Avatar answered Dec 04 '25 12:12

Michał Šrajer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!