659
Comment: Nice site! com website brown n bag recipe for pork tenderloin its http://arradn.servik.com/recipe6395.html fudgesicle recipe size, http://italy65.myd.net/recipe7628.html fun and easy snacks recipes,
|
2488
fix read in the final example and add alternative with '' instead of $'\0'
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
<<Anchor(faq20)>> == How can I find and deal with file names containing newlines, spaces or both? == The preferred method is still to use [[UsingFind|find(1)]]: |
|
Line 2: | Line 5: |
---- /!\ '''Edit conflict - other version:''' ---- Nice site! com website brown n bag recipe for pork tenderloin its http://arradn.servik.com/recipe6395.html fudgesicle recipe size, http://italy65.myd.net/recipe7628.html fun and easy snacks recipes, Thank! Cool Site! The Best! ---- CategoryCategory |
{{{ find ... -exec command {} \; }}} |
Line 7: | Line 9: |
---- /!\ '''Edit conflict - your version:''' ---- Nice site! com website brown n bag recipe for pork tenderloin its http://arradn.servik.com/recipe6395.html fudgesicle recipe size, http://italy65.myd.net/recipe7628.html fun and easy snacks recipes, Thank! Cool Site! The Best! ---- CategoryCategory |
or, if you need to handle filenames ''en masse'', with GNU and recent BSD tools: |
Line 12: | Line 11: |
---- /!\ '''End of edit conflict''' ---- | {{{ find ... -print0 | xargs -0 command }}} or with POSIX {{{find}}}: {{{ find ... -exec command {} + }}} Use that unless you really can't. Another way to deal with files with spaces in their names is to use the shell's filename expansion ([[globbing]]). This has the disadvantage of not working recursively (except with zsh's extensions), but if you just need to process all the files in a single directory, it works fantastically well. This example changes all the *.mp3 files in the current directory to use underscores in their names instead of spaces. It uses [[BashFAQ/073|Parameter Expansions]] that will not work in the original BourneShell or POSIX shell, but should be good in KornShell and [[BASH]]. {{{ for file in *.mp3; do mv "$file" "${file// /_}" done }}} Remember, you need to '''quote all your [[BashFAQ/073|Parameter Expansions]] using double quotes'''. If you don't, the expansion will undergo WordSplitting (see also BashGuide/TheBasics/ArgumentSplitting and BashPitfalls). You could do the same thing for all files with spaces in their names (regardless of extension) by using {{{ for file in *\ *; do }}} instead of *.mp3. Another way to handle filenames recursively involves using the {{{-print0}}} option of {{{find}}} (a GNU/BSD extension), together with bash's {{{-d}}} option for read: {{{ # Bash unset a i while IFS= read -r -d $'\0' file; do a[i++]="$file" # or however you want to process each file done < <(find /tmp -type f -print0) }}} The preceding example reads all the files under `/tmp` (recursively) into an array, even if they have newlines or other whitespace in their names, by forcing {{{read}}} to use the NUL byte (\0) as its line delimiter. Since NUL is not a valid byte in Unix filenames, this is the safest approach besides using {{{find -exec}}}. `IFS=` is required to avoid trimming leading/trailing whitespace, and `-r` is needed to avoid backslash processing. In fact, `$'\0'` is equivalent to `''` so we could also write it like this: {{{ # Bash unset a i while IFS= read -r -d '' file; do a[i++]="$file" done < <(find /tmp -type f -print0) }}} |
How can I find and deal with file names containing newlines, spaces or both?
The preferred method is still to use find(1):
find ... -exec command {} \;
or, if you need to handle filenames en masse, with GNU and recent BSD tools:
find ... -print0 | xargs -0 command
or with POSIX find:
find ... -exec command {} +
Use that unless you really can't.
Another way to deal with files with spaces in their names is to use the shell's filename expansion (globbing). This has the disadvantage of not working recursively (except with zsh's extensions), but if you just need to process all the files in a single directory, it works fantastically well.
This example changes all the *.mp3 files in the current directory to use underscores in their names instead of spaces. It uses Parameter Expansions that will not work in the original BourneShell or POSIX shell, but should be good in KornShell and BASH.
for file in *.mp3; do mv "$file" "${file// /_}" done
Remember, you need to quote all your Parameter Expansions using double quotes. If you don't, the expansion will undergo WordSplitting (see also BashGuide/TheBasics/ArgumentSplitting and BashPitfalls).
You could do the same thing for all files with spaces in their names (regardless of extension) by using
for file in *\ *; do
instead of *.mp3.
Another way to handle filenames recursively involves using the -print0 option of find (a GNU/BSD extension), together with bash's -d option for read:
# Bash unset a i while IFS= read -r -d $'\0' file; do a[i++]="$file" # or however you want to process each file done < <(find /tmp -type f -print0)
The preceding example reads all the files under /tmp (recursively) into an array, even if they have newlines or other whitespace in their names, by forcing read to use the NUL byte (\0) as its line delimiter. Since NUL is not a valid byte in Unix filenames, this is the safest approach besides using find -exec. IFS= is required to avoid trimming leading/trailing whitespace, and -r is needed to avoid backslash processing. In fact, $'\0' is equivalent to '' so we could also write it like this:
# Bash unset a i while IFS= read -r -d '' file; do a[i++]="$file" done < <(find /tmp -type f -print0)