I have the following script - its supposed to loop files names using find but it seams to break the files names up by a space? I need the file names to remain intact


for file in `find -name "*.avi"`
./myscript $file

Can anyone help me?



4 Answers 4

find -name "*.avi" -print0 | xargs -0 -n 1 echo

You don't have to echo in xargs:

find -name "*.avi" -print0 | xargs -0 -n 1 ./myscript
  • This is another way to output the filename - I need to loop file names to another script (in the example above I replaced the command with echo)
    – Rob
    Jul 8, 2012 at 15:38
  • So show us what you actually want to do then. We can't help you do what you want to do if you don't tell us what you want to do.
    – womble
    Jul 8, 2012 at 15:38

Also: find -name "*.avi" -exec ./myscript '{}' \;

Womble's answer definitely works in the majority of cases, but Xargs isn't perfect with spaces across all implementations. I've never found find's 'exec' mode to break. Solaris was particularly cranky in that respect.

Obviously, the '-print' would be better for simply generating output for a list of files in a for loop. But if you're running a command on a list of files, it's more efficient to just run the '-exec' option.


If you don't need recursion:


for file in *.avi
    ./myscript "$file"

Note that the quotes around the variable are essential.


As kojiro points out, if you need recursion and you have Bash 4, you can add shopt -s globstar and change the glob to **/*.avi.

  • If a file name has spaces, this method will break. If it has \n or other strange characters, it is also a security risk. Think of "/tmp/file\n/etc/shadow"
    – hayalci
    Jul 8, 2012 at 19:54
  • 1
    @hayalci: No, you are completely wrong. It works perfectly with such filenames and without any security risks. Globbing with a for loop is the correct way to do this when recursion is not needed. Jul 8, 2012 at 20:24
  • If he does need recursion and has bash 4, he can just use shopt -s globstar; for file in **/*.avi
    – kojiro
    Jul 8, 2012 at 22:13
  • @kojiro: Thanks, I should have mentioned that and I will add it to my answer. Jul 8, 2012 at 22:15
  • @DennisWilliamson: You are right, I confused the issue with "for i in `ls *.avi`" case
    – hayalci
    Jul 13, 2012 at 13:33

In addition to the solutions based on xargs and the find -exec there is also the option of piping to while read. It has the benefit of allowing you to structure your script in a more classic loop manner. Let me apply it to your example.

find -name "*.avi" | while read avifile; do
  ./myscript "$avifile"
  • 3
    By default read will support escaping, so you need -r. And your solution will break with filenames containing newlines. Jul 8, 2012 at 16:03
  • @Pierre: I have so far never encounted a regular space situation where I have needed the -r parameter (to read?), but thanks for the pointer, I'll look into it. Agree that this solution would break on newline. Assumed the original questioner only dealt with the regular space character. When expecting arbitrary whitespace, or any other really crazy characters I agree on xargs -0 being the better choice. Well, either that or doing something more robust in a language such as Perl, Python, etc.
    – andol
    Jul 8, 2012 at 16:12
  • 1
    -r is not needed for spaces, but in case a backslash appears in the filename. Jul 8, 2012 at 16:16

You must log in to answer this question.

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