I have a bash script that deals with files. It finds all the files in one directory and searches for the name of each in another directory. For that it uses


inside the script. However if the file name contains [ or ], the script won't find it in the second directory, even if a copy of the file is there as well. What can I do, so that the file names are recognized to be the same?

I was able to narrow the problem down to an example.

myfile="My File [Official Awesome File].txt"
find ./ -name "${myfile}" -type f

does give any output, even if there is a file with that name. To write \[ or something like that is of course not an option, because myfile comes from inspecting a directory.

Here is the script: https://gist.github.com/Make42/5bdae5e4de32cff0d01c9486b09383ee

  • 1
    Please show an example of code and inputs that demonstrate the problem. Otherwise we're just guessing – roaima May 1 '16 at 15:39
  • @roaima: I can show the entire script. Where can I do this? Should I post everything into the window or is there a better place to show more code? – Make42 May 1 '16 at 15:42
  • 1
    I'll try to extract the important part for a minimal working example. – Make42 May 1 '16 at 15:45
  • @roaima: Added an example. – Make42 May 1 '16 at 16:08
  • @don_crissti: The script I wrote looks into a first directory from where it takes the names of all the files in it. Then the script searches in a different directory whether it can find files with the same names from the first directory. This works as long the names of the files in the first directory do not have any [ or ] in them. I don't know why - only that my example (see question) does not work either. If I get the example to work, everything should work. – Make42 May 1 '16 at 16:19
myfile="My File [Official Awesome File].txt"
myfile=$(echo $myfile | sed -r 's/(\[|\])/\\\1/g')    
find ./ -name "${myfile}" -type f

can you check if this works?

I'm expecting this'll change value of myfile to

myfile="My File \[Official Awesome File\].txt"

Better would be to use printf:

myfile=$(printf '%q\n' "$myfile")

In your specific example within find that would be:

find ./ -name "$(printf '%q\0' "$myfile")" -type f
  • Seems to work in my example. However, I just realise that the issue here would be metacharacters in general. So how could I tell find to ignore metacharacters - except $ for this call? Could unix.stackexchange.com/a/141323/122989 be used somehow? – Make42 May 1 '16 at 16:49
  • yeah, I tried to search some option for that in find command, didn't get any.. so resorted to this hack.. will update if I find any – Sundeep May 1 '16 at 16:52
  • Maybe this: unix.stackexchange.com/a/141320/122989 – Make42 May 1 '16 at 16:52
  • myfile=$(printf '%q\n' "$myfile") gives My\ File\ \[Official\ Awesome\ File\].txt – Sundeep May 1 '16 at 16:58

The argument to find's -name parameter is a glob pattern, not a file name, and square brackets are glob pattern metacharacters.

I found one way around this is to use an in-line perl script which uses an exact-string match instead of a pattern:

myfile="My File [Official Awesome File].txt"
perl -MFile::Find -le 'find( sub {
  return unless $_ eq $ARGV[0];
  print $File::Find::name;
}, $ARGV[1] )' "${myFile}" .

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.