5

I have the following command :

ls /some/path/*dat | xargs -n 1 -I @ sh -c "echo `basename @`"

with the directory /some/path/ containing :

/some/path/a
/some/path/b
/some/path/c
/some/path/d

I want to get the output :

a
b
c
d

But I'm still getting full paths. What am I doing wrong ?

edit: BTW, I know that there is an easier way, I can just run basname instead of

echo `basename @`

But I need to run a complex command, something like

octave --silent --eval "somefunction('`basename @`','@',...))"

edit2:

Here is the actual command :

 ls ~/phd/data/conll2012/dev.megam/*dat | xargs -P 16 -n 1 -I@ timeout -k 1s 15m sh -c "if [ ! -f '~/phd/xp/conll2012/dev.megam/@.$epsilon$mink$minn$alpha' ]; then octave --silent --eval \"xprp('~/phd/xp/conll2012/dev.megam/@.$epsilon$mink$minn$alpha.rp','@',$alpha,$mink,$minn,$epsilon);\" 2>> ~/xpgrid.log;fi"

Basically, I have a set of files in a directory and this command feeds on these files to output result in another directory, checking if the result is not already there.

So, I need both files with fullpath and files with only basename.

How to make it work on ? The easier example at the beginning can help make this clearer.

  • Why not just find /some/path/ . -name "*dat" -exec basename {} \;? – fedorqui Nov 4 '14 at 15:20
  • Why not just for file in path/*dat; do ...; done eliminating ls altogether? – jimmij Nov 4 '14 at 15:34
3
ls /some/path/*dat | xargs -n 1 -I @ sh -c 'echo `basename "@"`'

The basename is executed too early in your code.

If you are not sure that there are no spaces or tabs in the paths then you should use -d \\n (or find ... -print0 | xargs -0 ...) and mind the " around the @.

  • 3
    Or -printf '%f\0' if using GNU find so you don't even need basename. (cd /some/path && printf '%s\0' *dat) would probably even make more sense. – Stéphane Chazelas Nov 4 '14 at 15:32
3

The testcase can be fixed simply by changing the double quotes to single quotes, but you might like to know about GNU parallel.

You can do the same thing like this:

parallel echo {/} ::: /some/path/*dat

(You may need to quote the curly braces, in some shells.)

As well as having clearer syntax, parallel will run the multiple commands at once.

Your second example would look like this:

parallel octave --silent --eval "\"somefunction('{/}', '{}', ...)\"" ::: /some/path/*dat

(You have to have quotes within quotes because it gets evaluated twice.)

  • I believe the last command can be quoted using -q thus getting rid of \" – Ole Tange Nov 6 '14 at 18:55
0
 # find all my perl file names with *.pl or *.pm ext sorted 
 find src/ -name '*.pm' -o -name '*.pl'  \
  | xargs -n 1 -I @ sh -c 'echo `basename "@"`' | sort

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.