3

My aim is to find $files on some $devices and save them to one or more folders which are namend corresponding to a timestamp of each file. To get the timestamp I wanted to use stat.

In contrast to echo "$files", stat doesn't process each file separately. Instead it seems to process all files at once when I use "".

Do you have any suggestions on how to improve quoting or any other hints on how to make stat able to do what i want it to do? Thank you very much for your help.

#!/bin/bash
for devices in "$(ls /media/*/)";
  do
    for files in "$(find /media/*/$devices -iname *.jpg)";
      do
        echo "$files"   # prints all files in separate lines
        stat "$files"   # seems to process all files at once
        stat $files     # splits file paths at spaces
      done
  done
2

The problem is not with stat but with the source data in your for loop; because you have enclosed it all in quotes it becomes one long single entity.

To fix this, remove the quotes around it, thus:

for files in $(find /media/*/$devices -iname "*.jpg");

It works provided that none of the files or paths have spaces. But there is a more elegant solution which works with spaces and even with weird filenames (for instance ones that include quotes or newlines):

while IFS= read -r -d '' file; do
    # operations on each "$file" here
done < <(find /media/*/$devices -type f -iname *.jpg -print0)
  • re alternate suggestion: that's because this uses $file not $files, which is really better since each $file is an individual file. I'm revising my initial suggestion, but the alternate is better really. – gogoud Mar 21 '15 at 11:44
  • Your alternate suggestion works for me (filenames with spaces) very well, thank you! – ha2k Mar 21 '15 at 11:47
1

Don't parse the output of ls. You can't distinguish a newline introduced by ls from a newline in a file name. The same goes for find.

for devices in $(ls /media/*/) is just a complex, broken way of writing for devices in /media/*/*. Instead of for files in $(find …); do …; done, use find … -exec ….

You don't need the two loops here, since you're only enumerating files in order to use the full set later. Your script is simply

find /media/*/* -iname '*.jpg' -exec stat {} +

For more information, see Why does my shell script choke on whitespace or other special characters?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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