12 ms·
I noticed that last week and was quite surprised by it. I was writing a script to get the permissions of all files. I wrote something like ls -l | grep -oE '^[
by benibela 5y ago
I noticed that last week and was quite surprised by it.
I was writing a script to get the permissions of all files. I wrote something like ls -l | grep -oE '^[^ ]+' and ran it in my home directory for testing. And then I was surprised that the output was wrong. Turned out I had files with \n in their name there and ls was printing them on two lines which confused the grep. (I still used that script, since I did not have any \n files on the real system)
I was actually building an exam for a course involving shell scripting. A common question was, do something with all the files in the current directory, like grep them or delete them. The lecture notes said to use * for all those files, but then I realized rm * would not work in all possible cases. I spend like an hour to find a hopefully correct solution. However, the professor said, the students would never figure it out in an exam, and I should just put * as model solution. The shells is extremely brittle
- grumbel 5y agoWhen dealing with filenames one has to get used to always using '\0' separated output instead of newline separated output, as filenames in Linux can contain everything except '\0' and '/'. Luckily most tools are prepared for this and have options to either output '\0' separators or accept them as input. Dealing with all the files in the current directory would look something like this (for demonstration, can be made shorter by using '-name' or '-regex' option from 'find'): find . -maxdepth 1 -type f -print0 | grep -z needle | xargs -n 1 -0 echo Looping over '\0' separated output is possible as well with this: find . -print0 | while read -r -d $'\0' filename; do echo "$filename"; done It stops being brittle when used correctly, but can take a bit getting used to and can get a little verbose.
- benibela 5y agoThe one I found to delete all files was rm -- .[!.]* ..?* * 2>/dev/null