Bash for each file with spaces


















Then it looks at each character in the output of find. As soon as it sees any character that's in IFS , it thinks that marks the end of the file name, so it sets file to whatever characters it saw until now and runs the loop. Then it starts where it left off to get the next file name, and runs the next loop, etc.

That sets IFS to a single newline, so it only splits on newlines, and not spaces and tabs as well. That is probably enough to get your script working, but if you're interested to handle some other corner cases properly, read on It could contain spaces, but since we already set IFS above, that won't be a problem here.

Thanks to Gilles for pointing this out. This is because inside the loop, standard input is coming from find via the pipeline. If we just did read , it would be consuming part or all of a file name, and some files would be skipped.

Note that this will cause an error if the script is run via cron, but I assume this is not important in this case. We can handle that by changing -print to -print0 and using read -d '' on the end of a pipeline:. This makes find put a null byte at the end of each file name. Null bytes are the only characters not allowed in file names, so this should handle all possible file names, no matter how weird.

Where we used read above, we used the default line delimiter of newline, but now, find is using null as the line delimiter. In bash , you can't pass a NUL character in an argument to a command even builtin ones , but bash understands -d '' as meaning NUL delimited.

So we use -d '' to make read use the same line delimiter as find. To be correct, we also add -r , which says don't handle backslashes in file names specially. A more portable way of writing this that doesn't require bash or zsh or remembering all the above rules about null bytes again, thanks to Gilles :. As glenn jackman points out, in both of these examples, the commands to execute for each file are being run in a subshell, so if you change any variables inside the loop, they will be forgotten.

If you need to set variables and have them still set at the end of the loop, you can rewrite it to use process substitution like this:. I removed the semi-colons ; inside the loop. You can put them back if you want, but they are not needed. It reads a whole line so I changed it to read line. The find command outputs one file name per line. You can avoid most problems at this stage by toning down word splitting and turning off globbing.

To tone down word splitting, set the IFS variable to a single newline character; this way the output of find will only be split at newlines and spaces will remain. To turn off globbing, run set -f. Then this part of the code will work as long as no file name contains a newline character. They have the same meaning, but the backquote version has weird quoting rules. Above, we knew we wanted to split the find output into lines.

A reliable way of calling find is telling it to run a command for each file it finds:. I'm surprised to not see readarray mentioned. D to also include hidden files, N to avoid the error if there's no match,. To print each value without splitting and solve the problem of previous example, you just need to enclose the array variable with double quotation within for loop. The first for loop is used to display array values in multiple lines and the second for loop is used to display array values in a single line.

Here, comma , is used to split the string values. IFS variable is used to set the field separator. In this example, two string arrays are defined and combined into another array.

Notice that it works with bash but not with other shells like dash for example. Here is a slight extension to Mitchell Currie's answer, that I like because of the small scope of side effects, which avoids having to set a variable:! Dandalf Dandalf 1 1 silver badge 4 4 bronze badges. I would write it like this: cat. Pipe and cat are unnecessary here. Better solution :! OMG yes! Pablo Bianchi 9, 3 3 gold badges 51 51 silver badges 92 92 bronze badges.

Hey odoncaoa , I tried to do the find command without the double quotes, but it makes all of the results appear as one line. I am confused about the "unknown amounts of input" with this command and the dangers involved. Can you provide an example of the dangers and how they could theoretically happen?

I seriously do not desire to be lazy about it, I am just more comfortable in other programming languages. The Overflow Blog. Podcast Helping communities build their own LTE networks. This is just one simple use case for setting a custom IFS. This site uses Akismet to reduce spam. Learn how your comment data is processed. Username or Email Address. Remember Me. Sign Up For Our Newsletter. Bash Scripting. Steven Vona , November 20,



0コメント

  • 1000 / 1000