I am working with a set of programs developed by others, many of which have special characters in their names. I may eventually want to change their names but that would have to wait until I understand them better. In the process of trying to gain that understanding, I've encountered some strange and apparently inconsistent behavior of some basic utilities. For example, there are several programs with single character names:
$ ls --quoting-style=shell-escape-always ? '#' ',' 'A' 'C' 'F' 'K' 'M' 'P' 'R' 'T' 'V' 'Y' "'" '`' 'B' 'D' 'H' 'L' 'O' 'Q' 'S' 'U' 'X' 'Z' If I try to search these files with grep, just pasting their names onto the command line, it works as expected. (Output piped here to wc simply for brevity in this message.) $ grep CALL '#' "'" ',' '`' 'A' 'B' 'C' 'D' 'F' 'H' 'K' 'L' \ 'M' 'O' 'P' 'Q' 'R' 'S' 'T' 'U' 'V' 'X' 'Y' 'Z' | wc 60 220 2901 But if I try to simplify that command by inserting the output of the ls command above, it doesn't work. $ grep CALL $( ls --quoting-style=shell-escape-always ? ) grep: '#': No such file or directory grep: "'": No such file or directory grep: ',': No such file or directory grep: '`': No such file or directory grep: 'A': No such file or directory ... The grep command above seems like it ought to behave exactly the same since it appears the command expands to the same thing. $ echo grep CALL $( ls --quoting-style=shell-escape-always ? ) grep CALL '#' "'" ',' '`' 'A' 'B' 'C' 'D' 'F' 'H' 'K' 'L' \ 'M' 'O' 'P' 'Q' 'R' 'S' 'T' 'U' 'V' 'X' 'Y' 'Z' There are many more files than just those with single character names (more than 4000 total) so I need to find a better solution. I've tried putting the names into a file with "ls --quoting-style=shell-escape-always >names", then using that file in my commands like "grep CALL $( <names )" but that yields the same "No such file" messages. I'm using the quoting-style option because many of the file names contain special characters that confuse the shell. If I omit that option for the single character files, things work correctly. $ grep CALL ? | wc 60 220 2901 $ grep CALL $( ls ? ) | wc 60 220 2901 Unfortunately, that simple approach doesn't work if I change the ? to * because of the special characters in many names. It does work if I use ./*. $ grep CALL ./* | wc 16325 61444 950870 $ grep CALL $( ls ./* ) | wc 16375 61601 953451 So I almost have a solution. Except the extra 50 lines found in the second command are disturbing. Thus far, it appears that those lines are duplicates and some of the duplicated lines are from files with names that do not contain any special characters. It appears to me that there are one or more inconsistencies in the treatment of file names in the output I've show above. Perhaps these are intentional or unavoidable for some reason. But I haven't seen any documentation that helps to clarify what's going on and why. Fedora release 36 x86_64 fully updated bash-5.1.16-2.fc36.x86_64 coreutils-9.0-8.fc36.x86_64 grep-3.7-2.fc36.x86_64 -- Dave Close, Compata, Irvine CA +1 714 434 7359 d...@compata.com dhcl...@alumni.caltech.edu "Words are too fragile to carry ideas." -- Dick Boyd