bash problem with if

#!/bin/bash

#  This script takes two arguments: <path> and <dir>. It has to copy in <dir>
#+ all regular files in <path> with .c extension containining at least one while
#+ instruction and one if instruction.

if [ "$#" -eq 2 -a -d "$2" ]
then
    for file in $(ls "$1" | grep "\.c$")
    do
      if [ -f "$file" ]  # doesn't work
      then
          a=$(strings "$1"/"$file" | grep -c while)
          b=$(strings -n2 "$1"/"$file" | grep -c if)

          if [ "$a" -gt 1 -a "$b" -gt 1 ] # doesn't work
          then
              cp "$1"/"$file" "$2"
          fi
      fi
    done

    exit 0
else
    echo "script use: `basename $0` <path> <dir>"

    exit 1
fi

I don't understand why those conditions don't work, especially that -f "$file".

Hi
Provide some more info, on how are you trying to run it. The script is taking a couple of arguments and it depends on quite a few things. The second argument should be directory, the first one should either be a .c file OR a directory containing .c files.

Guru.

As I wrote in the code first comment, this script must take two arguments, a pathname <path> and a directory <dir>, then it has to select every regular file with .c extension in <path> and to copy it in <dir>. You have understood correctly.

Here's the files I use:

luke@luke-desktop:~/Desktop/TEST$ ls
folder1 folder2
luke@luke-desktop:~/Desktop/TEST$ cd folder1
luke@luke-desktop:~/Desktop/TEST/folder1$ cat hello1.c
while
while
if
luke@luke-desktop:~/Desktop/TEST/folder1$ cat hello2.c
luke@luke-desktop:~/Desktop/TEST/folder1$

Here's the code when I run it, using ./folder1/ as <path> and ./folder2/ as <dir>:

luke@luke-desktop:~/Desktop/TEST$ bash -x es3 ./folder1/  ./folder2/
 + '[' 2 -eq 2 -a -d ./folder2/ ']'
 ++ grep '\.c$'
 ++ ls ./folder1/
 + for file in '$(ls "$1" | grep "\.c$")'
 + '[' -f hello1.c ']'
 + for file in '$(ls "$1" | grep "\.c$")'
 + '[' -f hello2.c ']'
 + exit 0

It is clear that

if [ -f "$file" ]

is always false, and if I comment it, then

if [ "$a" -gt 1 -a "$b" -gt 1 ]

is always false.

And I don't understand why, maybe some syntax errors?

Hi

When the file is being checked using the below:

 if [ -f "$file" ]
the script is still in the directory ~/Desktop/TEST . And hence it checks for the file hello.c in this directory and fails. Either change the directory before 'if' to ~/Desktop/TEST/folder1 or use the absolute path to check.

Guru.

1 Like

Try leaving out ls :

#!/bin/bash

#  This script takes two arguments: <path> and <dir>. It has to copy in <dir>
#+ all regular files in <path> with .c extension containining at least one while
#+ instruction and one if instruction.

if [ "$#" -eq 2 -a -d "$2" ]
then
    for file in "$1"/*.c
    do
      if [ -f "$file" ]  # doesn't work
      then
          a=$(strings "$file" | grep -c while)
          b=$(strings -n2 "$file" | grep -c if)

          if [ "$a" -gt 1 -a "$b" -gt 1 ] # doesn't work
          then
              cp "$file" "$2"
          fi
      fi
    done

    exit 0
else
    echo "script use: `basename $0` <path> <dir>"

    exit 1
fi
1 Like

Really cool man!

So using a for argument like this not only list $1 files, but also moves the control in $1 directory, and could be specified which file type must be selected.

Some questions about this method:

  1. Is there a way to list $1 files recursively ?
  2. Could more file types be specified after"/" ?
  3. Are there any other options besides "/" ?

Or better still, could you tell me everything you know about, please? :smiley:

Hi Luke,

It does not actually "moves the control" but rather just keeps the path attached to the file name. Just run this on the command line and see what the output looks like:

for i in ./folder1/*.c; do echo $i; done
  1. Not like this. You could do this:
for file in "$1"/*.c "$1"/*/*.c
do

Which would list any .c file in the directory an one level lower.
Otherwise you would have to do something like this:

find "$1" -name '*.c' | 
while read file
do
  1. Sure you can do, this for example:
for file in "$1"/*.[ch]
do

to list all *.c and *.h files

  1. I do not know what you mean with "option"

S.

I mean is there some other selection command to combine with "$1" argument in the for loop?

Hi Luke, the / in the example is literal slash character, not an option.

Yeah I expressed myself bad, however I think to understand.

Thanks for the help.