Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I was trying to find all files of a certain type spread out in subdirectories, and for my purposes I only needed the filename. I tried stripping out the path component via basename, but it did't work with xargs:

$ find . -name '*.deb' -print | xargs basename 
basename: extra operand `./pool/main/a/aalib/libaa1_1.4p5-37+b1_i386.deb'
Try `basename --help' for more information.

I get the same thing (exactly the same error) with either of these variations:

$ find . -name '*.deb' -print0 | xargs -0 basename 
$ find . -name '*.deb' -print | xargs basename {}

This, on the other hand, works as expected:

$ find . -name '*.deb' -exec basename {} \;
foo
bar
baz

This happens on up-to-date Cygwin and Debian 5.0.3. My diagnosis is that xargs is for some reason passing two input lines to basename, but why? What's going on here?

share|improve this question
2  
captcha: "coffees banned". NOOOOOOOOO!!!! –  quack quixote Oct 8 '09 at 16:01

4 Answers 4

up vote 17 down vote accepted

because basename wants just one parameter... not LOTS of. and xargs creates lots parameters.

to solve your real problem (only list the filenames):

 find . -name '*.deb' -printf "%f\n"

which prints just the 'basename' (man find):

 %f     File's name with any leading directories 
        removed (only the last element).
share|improve this answer
    
oooh.... /slaps forehead again/ i think i need a "find for dummies" book... –  quack quixote Oct 8 '09 at 16:17

Try this:

find . -name '*.deb' | xargs -n1 basename
share|improve this answer
    
this is not the explanation, this is a workaround. and the workaround is as good as just calling 'basename' via -exec for any file found. –  akira Oct 8 '09 at 16:07
3  
+1 ... while not an explanation, this would lead me to investigate the xargs switch you show, which would eventually lead me to the forehead-slapping motion i just used reading akira's and john t's answers... –  quack quixote Oct 8 '09 at 16:14
    
This is how I do it. I don't feel like learning all the ins and outs of the find command, so I only use it for finding and listing files, and I use xargs for everything else. –  Ryan Thompson Oct 8 '09 at 22:52

basename only accepts a single argument. Using -exec works properly because each {} is replaced by the current filename being processed, and the command is run once per matched file, instead of trying to send all of the arguments to basename in one go.

share|improve this answer

xargs can be force to just pass one arg as well...

find . -name '*.deb' -print | xargs -n1 basename

This works, however the accepted answer is using find in a more appropriate way. I found this question searching for xargs basename problems as I'm using another command to get a list of file locations. the -n1 flag for xargs was the ultimate answer for me.

share|improve this answer

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.