1

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/?

2
  • 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, 2013 at 18:31
  • @Emmanuel yes it is a better proposal in fact. thanks.
    – sourav c.
    Nov 29, 2013 at 18:35

2 Answers 2

4

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.

1
  • 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.
    – sourav c.
    Nov 28, 2013 at 18:00
1

This illustrates why you should NEVER rely on parsing the output of the ls command to iterate over directory contents - use a simple find command:

find . -maxdepth 1 -type d --regex './[0-9]+$' -exec cp $1 {} \;

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .