0
$ bash --version
GNU bash, versione 5.2.26(1)-release (x86_64-pc-linux-gnu)

I don't know how to deal with $VAR when its value inside contains single quote (') and/or backtick (`).

I'm in the need of executing find's -exec based on entries found in list.txt.

list.txt contains:

  • one FILENAME.EXT per line
  • each line ends with newline (\n)

As a preventive test to verify everything is OK, I run these:

$ while IFS= read -r song; do find /mnt/EXTHDD/unsorted -type f -name "$song"; done < list.txt
$ while IFS= read -r song; do find /mnt/EXTHDD/unsorted -type f -name "*$song*"; done < list.txt
$ while IFS= read -r song; do find /mnt/EXTHDD/unsorted -type f -name '$song'; done < list.txt
$ while IFS= read -r song; do find /mnt/EXTHDD/unsorted -type f -name "${song}"; done < list.txt

None worked...

Unfortunately, not all occurrences are listed due to Special Characters in FILENAME and thus $song variable cannot be quoted correctly (neither with double quotes, nor single quotes).

Example of lines FILENAME.EXT found in list.txt:

Pino Daniele ~ [2000] Napul`e' - Raccolta completa ~ 01.14) `O ssaje comme fa `o core.mp3
[CONCERTI] Malora -- Live@TANT`E'! (Agosto '05, Villa Fossa` [presa diretta, mixer:stereo]) -- #15. 20:30 ... Tutto tace?.wave
5
  • 3
    I'd bet that the problem isn't the quotes. The problem is the text in [...], which is a shell glob, e.g., [2000] matches a 2 or 0, [CONCERTI] matches C, O, N, E, R, T or I.
    – muru
    Commented Mar 30 at 8:28
  • 2
    "$song" and "${song}" (and "*$song*", if you want to pass asterisks) are properly quoted and the value of the variable cannot break them. Bash cannot store null bytes in a variable, but filenames (pathnames in general) also cannot contain null bytes, so this shouldn't be a problem in this usage case. AFAIK everything else can be stored in a variable. If your code does not work as expected, it's not because allegedly "the variable cannot be quoted correctly"; it can. Commented Mar 30 at 8:30
  • Too bad find doesn't have the equivalent of grep -F. Not even in GNU find, even though it supports various regex dialects via the -regextype option.
    – ilkkachu
    Commented Mar 30 at 10:36
  • @muru I didn't know the exact -name (or -iname) behaviour in find; you're right, indeed. Thanks, dear! unix.stackexchange.com/questions/773436/… yes! This helped me
    – dAllARA
    Commented Mar 30 at 11:23
  • Dear members all... Should I edit my question in order to clarify the actual issue? Let me know.
    – dAllARA
    Commented Mar 30 at 11:38

1 Answer 1

1

The problem here are NOT single quote (') and/or backtick (`).

Rather, I needed to escape square brackets ([ and ]) in order to prevent GNU find interpreting values of -name (or -iname) as a glob.

Super thanks to muru and Kamil Maciorowski for pointing me to the right direction!

Here's how I solved with this oneliner:

while IFS= read -r song; do 
  unsquare=$(printf '%s\n' "$song" | sed 's/\[/\\[/g;s/\]/\\]/g') && 
   find /mnt/EXTHDD/unsorted -type f -name "$unsquare" 
done < list.txt
1
  • 1
    This is still a oneliner, I just split to multiple lines for clarity. You can still copy/paste directly into a terminal but this is much easier to read on this page than having it on a single line.
    – terdon
    Commented Mar 30 at 15:25

Not the answer you're looking for? Browse other questions tagged .