Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Well, I think you can find dozens of questions on this platform how to pipe find output to sed, but I haven't found anything for the reverse direction so far. What I want to do is modify my input, and then pass it to find.

Supposing I want to do something like the following, in order to make life easier for myself by avoiding to type in those cumbersome asterisk wildcards. (I hope it's obvious enough that the expression which follows the triple redirection operator <<< is eventually planned to get replaced by a parameter, e. g. $1, in a script later. The line below is merely for demonstration.)

$ sed 's/ /\*/g' <<< ' foo bar baz ' | find . -type f -iname - 

That - at the end of this one-liner was actually supposed to use the output of sed as input for find; however, extending the find part to

... find -D tree . -type f -iname - ... 

revealed that the parameter was not passed to find. Perhaps you cannot pass pre-processed input to find using a pipe at all?

share|improve this question
    
"foobar*baz" (testing something) –  Michael Mrozek Sep 26 '12 at 14:04

2 Answers 2

up vote 5 down vote accepted

find doesn't take its args from stdin, it takes them from the command line, so:

find . -iname "$(sed 's/ /\*/g' <<< ' foo bar baz ')"

That will become:

find . -iname "foo*bar*baz*"

(the quotes are necessary to stop the shell from expanding the wildcard foo*bar*baz*)

which may or may not be what you were hoping to get. e.g. if you really wanted files beginning with either foo, bar, or baz rather than files matching the patter 'foo*bar*baz*' then you need to construct a regexp and use -regex or -iregex rather than -iname. or construct a more complicated find command like -iname 'foo*' -o -iname 'bar*' -o -iname 'baz*'

alternatively:

PATTERN='foo bar baz'
PATTERN=$(echo "$PATTERN" | sed -e 's/ /*/g')
# and/or do whatever else you need to do to transform $PATTERN to be what
# you need it to be...
find . -iname "$PATTERN"

Here's the one-liner in a bash script. it works exactly the same in the script as it does on the command-line.

$ cat ./test.sh
#! /bin/bash 
find . -iname "$(sed 's/ /\*/g' <<< ' foo bar baz ')"

$ ls -l
total 4
-rw-r--r-- 1 cas cas  0 Sep 26 16:53 doesntmatch
lrwxrwxrwx 1 cas cas 16 Sep 26 16:59 symlink -> xfoo-ybar-zbaz01
-rwxr-xr-x 1 cas cas 69 Sep 26 16:50 test.sh
-rw-r--r-- 1 cas cas  0 Sep 26 16:50 xfoo-ybar-zbaz01
-rw-r--r-- 1 cas cas  0 Sep 26 16:50 xfoo-ybar-zbaz02
-rw-r--r-- 1 cas cas  0 Sep 26 16:50 xfoo-ybar-zbaz03

$ ./test.sh 
./xfoo-ybar-zbaz01
./xfoo-ybar-zbaz03
./xfoo-ybar-zbaz02

$ find . -iname "$(sed 's/ /\*/g' <<< ' foo bar baz ')"
./xfoo-ybar-zbaz01
./xfoo-ybar-zbaz03
./xfoo-ybar-zbaz02

$ find . -iname "*foo*bar*baz*"
./xfoo-ybar-zbaz01
./xfoo-ybar-zbaz03
./xfoo-ybar-zbaz02
share|improve this answer
    
Thanks! That first line will already do the trick for me. Whilst lots of commands do support stdin, find obviously doesn't. However, I assumed that it did. :) By the way, surely you meant that there is an asterisk before "foo", as well. However it got filtered out! (I suspect it's a SE bug?) IMPORTANT: The first line will NOT work within a standalone script! Analysed it again using the find -D tree ... debug mode. The ' foo bar baz ' stuff will have to be replaced by double quotes " foo bar baz ". Yes, that's right: double quotes inside double quotes. And that's fine. –  syntaxerror Sep 26 '12 at 2:38
    
sorry, i copy-pasted it but i didn't even notice that leading space, so i didn't include it in what i actually typed. feel free to add it yourself :). How are you using the find... "$(sed...)" line? It worked for me just now when i put it in a one-line bash script. –  cas Sep 26 '12 at 6:52
    
No, Craig, that's what I was trying to point out: I CANNOT ADD IT. That "leading asterisk" will get automatically removed as soon as I submit my post. It must be a bug. To your question: I'm using it in a one-line bash script as you do. But I don't get any search results unless I put the "foo bar baz" expression in double quotes, that's a fact. :) –  syntaxerror Sep 26 '12 at 12:31
    
i've added my test.sh script and sample output. the find command works exactly the same in the script as it does on the command line, and they both produce the output i expect to see. the final output shows typing the find command in without using sed to transform spaces into asterisks. –  cas Sep 26 '12 at 22:33

Why don't you use a for loop?

for n in $(sed 's/ /\*/g' <<< ' foo bar baz '); do find . -iname $n; done
share|improve this answer
    
Because I actually only wanted to run find one time, not n times. By the way, you've got a variable mismatch in your line. –  syntaxerror Sep 25 '12 at 23:33
    
That's a good reason and I've corrected the variable, well spotted. –  terdon Sep 25 '12 at 23:39

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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