How to list dirs containg a file?

0

1

I'm trying to use find to list dirs with a certain file inside, but my dirs have spaces so I haven't found a solution.

user74478

Posted 2011-03-15T02:58:09.870

Reputation:

1It's not clear what you want to do. Can you be more specific? – Paused until further notice. – 2011-03-15T04:17:58.937

If you're worried about compatibility, wouldn't a simple perl script using the standard File:Find module instead? That would probably work reliably on any platform. – Phil Hollenback – 2011-03-15T06:42:33.923

Phil, I'm not a perl programmer i'm a python programmer. – None – 2011-03-16T17:17:26.413

Answers

1

Assuming I'm really understanding your question, have you tried:

find / -name "*what*" -exec dirname {} \;

This works for me even if my directories have spaces:

root:~# find / -name "*what*" -exec dirname {} \;
/usr/share/man/id/man1
...
...
/usr/share/man/ja/man1
/usr/share/man/it/man1
/usr/share/man/man1
/usr/bin
/root/This is a Spaced Dir

jliendo

Posted 2011-03-15T02:58:09.870

Reputation: 143

This doesn't work on OS X – None – 2011-03-16T17:18:18.783

0

POSIX dictates a rather weak find (seriously, it doesn't even have -print0). Likewise, xargs won't have an -0 option, and IEEE 1003.1-2008 considers xargs -I {} to be an X/Open System Interface extension (which both declares a string to substitute with arguments and converts xargs to using newlines for input argument separators). Thus, assuming you actually want to do something with the path names other than printing them out and if you can only use base POSIX, you'll need to escape the spaces in the strings before passing them to xargs, thus:

find /startingdir -name 'file name' -exec dirname {} \; | sed 's/ /\\ /g' | xargs command

Note that you'll also need to escape quotes and backslashes, if you have directories that include these. This could replace the sed command:

sed -e 's/\\/\\\\/' -e 's/ /\\ /g' -e 's/"/\\"/g' -e "s/'/\\\\'/g"

(Note the extra backslashes on the double quoted script. Single quote strings use backslashes literally, but double quote strings will interpret backslashes, thus your shell will interpret "\\\\" as \\ which sed needs for a literal \, while '\\\\' is interpreted as \\\\ which sed needs for a literal \\.) This will escape existing backslashes first, then escape spaces, double quotes and single quotes.

If you can use the X/Open System Interface extensions, then the first version (no quotes or backslashes) simplifies to:

find /startingdir -name 'file name' -exec dirname {} \; | xargs -I {} command {}

If you have quotes and backslashes in your directory names, these will still need to be escaped as above (but without escaping spaces).

Either way, if you have newlines in your directory names, then you've got bigger problems than I can help with.

Edited to remove bash version, cleaned up based on input from Dennis Williamson

DerfK

Posted 2011-03-15T02:58:09.870

Reputation: 917

There are many errors in your answer. To start with, your assignment to IFS won't work. You should never iterate over the output of find using a for loop. If you want to be portable and POSIX compliant, don't use echo. You could use sed, but why not use dirname. In one place you use $() which is specified by POSIX, but in another you use backticks which, while also POSIX, are less desirable. You fail to mention the find operator -exec. You fail to quote a variable containing a filename. The question is tagged [posix] but not tagged [bash] so sh should be assumed. – Paused until further notice. – 2011-03-15T04:17:16.237

OK, I'll clean this up, though I'll be leaving it written for the assumption that he wants to do something with the list of directories, rather than just displaying them (otherwise, would it really merit mentioning spaces as a problem?). I'll even take out the bash version of my answer, which I had written before seeing the posix tag. – DerfK – 2011-03-15T05:34:45.203

Thanks, your first example worked. Now that I think about it sed would work for escaping spaces. – None – 2011-03-16T17:14:02.780

0

This is from the fedora .bashrc file:

ff () {
       find . -name "*$@*" -print;
       }

Add this to your .bashrc and then reinitialize your bash shell

now you can use ff <whatever > \ <whatever>

The \ is the escape sequence to escape special characters.

Nandhini Anand

Posted 2011-03-15T02:58:09.870

Reputation: 185

0

zsh is not my preferred shell, but for this task its **-function is invincible:

zsh -c "'ls **/'the file name'"

Or even:

zsh -c "ls **/*'file name'"

Ole Tange

Posted 2011-03-15T02:58:09.870

Reputation: 3 034