1

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

"${myfiletobesearched}"

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

Jakuje
  • 21,357
Make42
  • 657
  • 1
    Please show an example of code and inputs that demonstrate the problem. Otherwise we're just guessing – Chris Davies May 01 '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 01 '16 at 15:42
  • 1
    I'll try to extract the important part for a minimal working example. – Make42 May 01 '16 at 15:45
  • @roaima: Added an example. – Make42 May 01 '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 01 '16 at 16:19
  • @don_crissti: Since I am not sure how to explain it best, I added a link to the code. Quick answer: Via while loops. – Make42 May 01 '16 at 16:27

2 Answers2

1
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
Make42
  • 657
Sundeep
  • 12,008
  • 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 http://unix.stackexchange.com/a/141323/122989 be used somehow? – Make42 May 01 '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 01 '16 at 16:52
  • Maybe this: http://unix.stackexchange.com/a/141320/122989 – Make42 May 01 '16 at 16:52
  • myfile=$(printf '%q\n' "$myfile") gives My\ File\ \[Official\ Awesome\ File\].txt – Sundeep May 01 '16 at 16:58
0

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}" .
Billious
  • 219