Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I made this simple script to copy a file recursively to many sub-directories. Here I am showing the problem for 3 sub-directories. I have 3 sub-directories and 2 files in a directory as follows

0.003/  0.007/  0.015/  program.cpp  driver.sh*

I want to copy program.cpp to all these sub-directories using myscript.sh shown below:

    #!/bin/bash
    mydir=`pwd`

    for i in `ls -la $mydir | grep "[0-9]$" | awk '{print $NF}'`
    do
        if [ -e $mydir/$1 ]
        then
            echo "cp -i $1 $i/"
        else
            echo "File \"$1\" not found in current directory"
        fi
    done

I have put the cp inside echo to test the code. The output is strange,

cp -i program.cpp 32/
cp -i program.cpp 0.003/
cp -i program.cpp 0.007/
cp -i program.cpp 0.015/

The output of ls -la

total 32K
drwxr-xr-x. 5 gulu workg 4.0K Nov 29  2013 .
drwxr-xr-x. 7 gulu workg 4.0K Nov 29  2013 ..
drwxr-xr-x. 2 gulu workg 4.0K Nov 26 19:09 0.003
drwxr-xr-x. 2 gulu workg 4.0K Nov 26 19:09 0.007
drwxr-xr-x. 2 gulu workg 4.0K Nov 26 19:09 0.015
-rw-r--r--. 1 gulu workg 4.2K Nov 29  2013 program.cpp
-rwxr-xr-x. 1 gulu workg  982 Nov 26 08:22 driver.sh

The output of ls -la $mydir | grep "[0-9]$" | awk '{print $NF}'

0.003
0.007
0.015

There are only three values in i then how is it producing four output? Anyway I have solved the problem with an additional condition [ -d $mydir/$i ]. But my question is how the script is producing the first line cp -i driver.sh 32/?

share|improve this question
1  
You could match the first "d" of the list. Note that awk can do what grep does: ls -la $mydir| awk '/^d.*[0-9]$/ {print $NF}' –  Emmanuel Nov 29 '13 at 18:31
    
@Emmanuel yes it is a better proposal in fact. thanks. –  souravc Nov 29 '13 at 18:35

1 Answer 1

up vote 2 down vote accepted

This illustrates why you should NEVER rely on parsing the output of the ls command to iterate over directory contents - use a simple shell glob instead e.g. to match any filename ending in a digit

for f in $mydir/*[0-9]
do
    if [ -e $mydir/$1 ]
    .
    .
done

As to how it is producing the line cp -i driver.sh 32/, you can see that when you grep for digits in the output of ls -la, it is matching the total: 32K line as well as the wanted directory names.

share|improve this answer
    
Ohh! now I got it when you point out of ls. I was finding flaw here and there before. Actually in my .bashrc I put an alias for ls as 'ls -h --color=auto'. That is why output of ls -la shown total 32K and filtered through grep with field ends with number discard it. But when the script is running I think it is using /bin/ls and taking four values reading first line as total 32. I learned a good lesson. Thanks a lot for your help. –  souravc Nov 28 '13 at 18:00

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.