Operating System - Linux
1753599 Members
6345 Online
108796 Solutions
New Discussion юеВ

Command substitution and file names with spaces

 
SOLVED
Go to solution
John Talaga
Advisor

Command substitution and file names with spaces

Hello all,

I have an interesting problem that I am having difficulty finding a simple solution for.

I am attempting to find all files on my system that contain a certain word 'someword', and do a long listing sorted by date of the results. The problem is that a certain amount of files that contain 'someword' on this system have spaces in the file names.

I am attempting to use command substitution, like in this example:

ls -alsrt `find . -type f -exec grep -l someword {} \;`

This works until find reaches a file with a space in it. For example, if I have a file listing similar to this:

./file1
./file2
./file 3
./file 4

...and file1, file2 and file 4 all have 'someword' in it, the command above will return the correct display for file1 and file2, but will display errors that no file exists for 'file' and for '4'.

Basically what I need to happen is the find command to pass the found filename to the ls command with double quotes around it, so that ls can properly display "file 4".

Any help would be greatly appreciated.
11 REPLIES 11
Steven E. Protter
Exalted Contributor
Solution

Re: Command substitution and file names with spaces

Shalom,

File names with spaces have to have double quotes around them.

ls -alsrt1 `find . -type f -exec grep -l someword {} \; > list`

while read -r filename
do
action "${filename}"

done < list

SEP
Steven E Protter
Owner of ISN Corporation
http://isnamerica.com
http://hpuxconsulting.com
Sponsor: http://hpux.ws
Twitter: http://twitter.com/hpuxlinux
Founder http://newdatacloud.com
John Talaga
Advisor

Re: Command substitution and file names with spaces

Steven,

This gets me 90% of the way there. Thank you very much.

Based on your post, this is what I came up with:

find . -type f -exec grep -l 'someword' {} \; > list

while read -r filename
do
ls -alsrt1 "${filename}"

done < list

The commands above will output a list of files with 'someword', including those with spaces in file names and directory names, but what we need it to do is to properly sort that output by date, as the ls -alsrt would imply.

This does not seem to happen here. It seems like it is running the ls -alsrt command on each line in the list file individually.

I have a thought that I could output this listing to a secondary list, and use cut and sort to get what I want, but that seems like this is taking the long way around.

Do you have any thoughts on how to efficiently get this output sorted by date?

Again, thanks tremendously for your help.
H.Becker
Honored Contributor

Re: Command substitution and file names with spaces

maybe this one-liner?

sh -c "ls -alsrt1 `find . -type f -exec grep -m 1 -q someword {} \; -printf \"'%p' \"`"
James R. Ferguson
Acclaimed Contributor

Re: Command substitution and file names with spaces

Hi John:

And now you see the horrors of files with whitespace --- the dumbest thing M$ ever allowed.

Try this:

# find . -type f -exec ls -art -1 {} \;|xargs -L1 -i grep someword {}

I suggest that your copy-and-paste the above to try it. Ones (1) and the letter 'l' look too much alike.

Regards!

...JRF...

Steven Schweda
Honored Contributor

Re: Command substitution and file names with spaces

> [...] the dumbest thing M$ ever allowed.

And which UNIX (or UNIX-like) OS doesn't also
allow spaces in a file name? And who allowed
it earlier?
James R. Ferguson
Acclaimed Contributor

Re: Command substitution and file names with spaces

Hi (again):

> And which UNIX (or UNIX-like) OS doesn't also
allow spaces in a file name? And who allowed
it earlier?

Yes, good point. I should have said "the dumbest thing M$ ever made common in their standard for naming directories (or should I say 'folders')."

Regards!

...JRF...
H.Becker
Honored Contributor

Re: Command substitution and file names with spaces

I think the question was how can the "find" return the file names such that they can be used by "ls". The contents of the files - as found with grep - is the selection criterium for "ls". The found strings are not part of the result.

I'm sure, this is not news, here. In the shell, if you want to pass a file name with whitespace to "ls" you have to quote it. The shell then removes the quotes and passes the file name as a single argument to "ls". However, the shell does the remove of the quotes before it evaluates the command in backticks.

So you need "find" to return quoted file names, but it is too late for the shell to pass them with quotes removed to "ls". Therefore you need another "shell" to process the find result and let it remove the quotes to pass the wanted names as arguments to "ls". The "sh -c" does this. There may be other, better solutions.

I don't think it helps with the initial problem, but Unix file systems usually allow file names to contain any character other than "/". Whatever shell you use, you will have problems if the name contains shell metacharacters, special characters for pathname expansion and anything else the shell interprets or expands. But in general it seems that MS file systems have more restrictions to name a file than Unix file systems.
Mike Stroyan
Honored Contributor

Re: Command substitution and file names with spaces

H.Becker is very right to use "grep -q" so only the success is reported. (The "-m 1" option is redundant when "-q" is used.)

The find command does not need to use "-printf" with quotes for the shell.
It can use another "-exec" with "\+" to exec ls once with all the file names.

Either the "-printf" or the "-exec {} \+" method will get into trouble if the length of the arguments list is too long. In that case you would need to use an external sort. You could use the output of "stat -c '%Y %N' " to make the data easier to sort.

find . -type f -exec grep -q someword {} \; -exec ls -alsrt1 {} \+
John Talaga
Advisor

Re: Command substitution and file names with spaces

Hello all,

Thank you very much for the ideas. I got pulled away from this for a bit, but as soon as I can get back to it, I will update with results.

Thanks for all of your suggestions.

--John