diff --git a/Sc2044.md b/Sc2044.md new file mode 100644 index 0000000..689490c --- /dev/null +++ b/Sc2044.md @@ -0,0 +1,24 @@ +It is difficult to correctly use "find" in a for loop, because filenames can contain bytes such as newlines and "*". Where practical, consider using find's "-exec" like this: + + find . -exec COMMAND... {} \; + find . -exec COMMAND... {} \+ + +A portable though complicated approach is to use a subshell (use '\'' for each single quote), though since a subshell is used, all variable assignments in the loop are lost after the loop ends: + + find . -exec sh -c ' + for file do + ... # Use "$file" not $file + done' sh {} + + + +A nonstandard but widely-working simple alternative is: + + find . -print0 | xargs -0 COMMAND + +Using a find... while loop is another alternative. This requires nonstandard extensions to find (-print0) and shell (read -d), and fails in some cases on Cygwin (in while loops, filenames ending in \r \n and \n look identical to Cygwin). Variable values may be lost after the loop because the loop may run in a subshell: + + find . -print0 | while IFS="" read -r -d "" file ; do ... + COMMAND "$file" # Use quoted "$file", not $file, everywhere. + done + +For more information, see "[Filenames and Pathnames in Shell: How to do it Correctly](http://www.dwheeler.com/essays/filenames-in-shell.html)".