0

I have a find result saved in a variable and I am protecting the spaces in filenames by adding a single quotes around the output. So the for loop works flawlessly.

My problem is when I intend to grep one of those files, it says "File does not exist" because is literally taking the single quotes as part of the filename.

How can I overcome this??

all_files=$(find . -type f -printf "'%p'")

for file in $all_files
do
       grep 'hello' $file ### this says "file.not found because of the single quotes
done
3

If you want to store the file list to later loop over it, best would be to store it in an array.

With bash:

readarray -td '' all_files < <(find . -type f -print0)
for file in "${all_files[@]}"; do
  grep hello "$file"
done

With zsh (same thing but get a sorted list as a bonus):

all_files=(./**/*(ND.))
for file ($all_files) grep hello $file
4

You're not protecting the value of the filenames by adding quotes to it in the output of find. The loop would still see 'a filename' as two things to iterate over. The quotes would also be part of the string, as you noticed.

Instead, run your grep from find:

find . -type f -exec grep 'hello' {} \;

This would execute grep once for each file found.

find . -type f -exec grep 'hello' {} +

This would execute grep for as many files as possible at once (and thus also output the file names for batches with more than one file, use the -h option with GNU grep or compatible to not print the file name).

Still with GNU grep:

grep -D skip -r 'hello' .

This would run grep recursively on the current directory, skipping non-regular files (like -type f does for find), but would still look into symlinks to regular files (as if using GNU find -xtype f).

3

Print all the file names having the pattern 'hello',

find . -type f -print0 | xargs -0 -L1 grep -l 'hello'

OR with a find with grep inline

find . -type f -exec grep -l 'hello' {} \;

OR more simply (in case you have only regular files)

grep -Rl 'hello' .
  • 1
    Note that -R is not a standard option. In modern versions of GNU grep, -R (as opposed to -r) follows symlinks when recursing as if using find -L. – Stéphane Chazelas Mar 24 at 9:27
0

For anyone interested in how I solved this, I ended up with :

all_files=$( find . -type f -name *.txt -printf '%p' )

while read file
do
        grep 'hello' "$filename"
        .....
done <<< "$all_files"

I know it's a bad practice. But for my specific use case I needed to do a lot of things over each filename. Not just grepping. And it worked flawlessly now.

Thanks!

  • This would not work if there was more than one .txt file in the current directory (the find command would fail). The filename in the grep command has a trailing single quote inserted, and the names of the files would still have literal single quotes appended to them. I can't see how this solves anything. – Kusalananda Mar 24 at 14:37
  • @Kusalananda yeah. I obviously wrote this by hand. That's why it contains errors. And no. There are several files with spaces in the same directory. There is even files with multiple spaces in both the directory names and the file names simulataneously and it worked perfectly. Having said that, there are two design flaws in place here : – Matias Barrios Mar 24 at 14:41
  • 1) I have to do all of this non sense because some brilliant engineer decided it was an awesome idea to name both directories and files with spaces inside certain MacOs system folders. – Matias Barrios Mar 24 at 14:42
  • 2) I do not understand why spaces in filenames are allowed in the first place by both Linux and MacOs. Juts force the users to use underscores. – Matias Barrios Mar 24 at 14:43
  • 1
    Spaces and newlines and tabs (and * and all sort of emojis and other characters) are allowed. Only / and null bytes are not allowed in names of files. Did you try any of the other proposed solutions? Did you find problems with them. If so, leave a comment and let us know what was not working so that we may give you an even better answer. – Kusalananda Mar 24 at 14:44

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.