Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I would like to use the find command in a for. So I did this:

for logs in `find $BACKUP_FOLDER -exec ls -la {} \; | awk '{ if ( $8==2011) printf $0"\n" }'`; do
// some command here
done;

But it seems to not be working, so if I try to find out how the command is being interpreated, I put this line alone in my script:

echo "$BACKUP_FOLDER -exec ls -la {} \; | awk { if ( '$8'==2011) printf $0"\n" }";

And the $8 appears blank and the \n is blank too. This is what is printed in terminal

/company-logs/engine -exec ls -la {} \; | awk { if ( ''==2011) printf /company/scripts/server/backup/sync_backup.shn }

How can I fix this ?

share|improve this question

1 Answer 1

up vote 3 down vote accepted

Your question

echo "$BACKUP_FOLDER -exec ls -la {} \; | awk { if ( '$8'==2011) printf $0"\n" }";

won't display anything useful for two reasons:

  • In order to see the command as it would get executed by the shell, you have to escape the special characters $ and " with a backslash.

  • $8 is just the eighth command-line argument for bash. To see what awk would replace it with, execute this command instead:

    find $BACKUP_FOLDER -exec ls -la {} \; | awk '{ if ( $8==2011) printf $0"\n" }'
    

Your approach

Your for loop doesn't work since printf $0 prints an entire line from ls -l (containing permissions, owners, date and time).

To fix this, you have to eliminate all but the bare file name using, e.g., awk itself or cut:

for logs in `find "$BACKUP_FOLDER" -exec ls -la {} \; | awk '{ if ( $8==2011) print $0 }' | cut -c 43-`; do ... done

This will create problems if there are spaces in the filenames. Setting the internal file separator to new-line only (IFS=$'\n' in bash) should take care of spaces.

Your problem

Your approach isn't very portable, since a different version of ls or a different locale might alter the fields.

To process all files from 2011, instead of your approach, I'd use

for logs in $(find "$BACKUP_FOLDER" -exec bash -c '[[ "$(stat -c %y "$0")" =~ ^2011 ]]' {} \; -print); do ... done

or, if possible,

find "$BACKUP_FOLDER" -exec bash -c '[[ "$(stat -c %y "$0")" =~ ^2011 ]]' {} \; -exec ... \;

Again, modifying the IFS should take care of spaces, but the second approach will be more reliable.

find replaces {} with the currently processed file and passes it as an argument to bash, which can access it as $0.

stat -c %y "$0" shows the modification time of $0 and [[ "$(...)" =~ ^2011 ]] checks if it begins with 2011.

If it does, bash -c '...' returns true and -print prints the filename or -exec executes a command.

share|improve this answer

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.