Wang
Wang

Reputation: 8173

xargs how to put result {} into $(cmd {})?

for example: find /usr/lib -maxdepth 1 -type l -iname "*libblas*"|xargs -I{} echo "{} =>" $(realpath {}) I would like it to output:

/usr/lib/libblas.so.3gf=>/usr/lib/libblas/libblas.so.3gf.0
/usr/lib/libblas.so=>/usr/lib/libblas/libblas.so.3gf.0
/usr/lib/libblas.a=>/usr/lib/libblas/libblas.a

This will not work because the value in $() is expanded before the script actual running.

Is there any way I can achieve this result? without loop in bash?

Upvotes: 3

Views: 311

Answers (5)

Ole Tange
Ole Tange

Reputation: 33685

The shortest seems to be using GNU Parallel:

find /usr/lib -maxdepth 1 -type l -iname "*libblas*"|parallel echo {} '=\> $(readlink -f {})'

Upvotes: 0

You need the command substitution to happen after the file name is known. So you need xargs to call a shell and do the substitution there.

Since you're running the command on a single file at a time, using xargs is a useless complication (and it also mangles some file names). Use -exec!

find /usr/lib -maxdepth 1 -type l -iname "*libblas*" -exec sh -c 'echo "$0 => $(realpath "$0")' {} \;

You could make this slightly faster and not less clear by not using a command substitution:

find /usr/lib -maxdepth 1 -type l -iname "*libblas*" -exec sh -c 'echo -n "$0 => "; realpath "$0"' {} \;

To make things a little faster, don't invoke a new shell process for every file:

find /usr/lib -maxdepth 1 -type l -iname "*libblas*" -exec sh -c 'for x; do echo -n "$x => "; realpath "$x"; done' _ {} +

(You can do the same with xargs, but just drop xargs and stick to the simpler, faster, more robust -exec.)

Upvotes: 1

ooga
ooga

Reputation: 15501

Alternatively:

find /usr/lib -maxdepth 1 -type l \
  -exec echo -n '{} =>' \; \
  -exec realpath '{}' \;

Upvotes: 4

user2743554
user2743554

Reputation: 543

Try to convert each filename separately using line-by-line "while" loop:

find ... | while read f; do echo "$f" '=>' "$(realpath $f)" ; done

Upvotes: 0

Ross Ridge
Ross Ridge

Reputation: 39581

Have xargs call the shell:

find /usr/lib -maxdepth 1 -type l -iname "*libblas*"|xargs -I{} sh -c 'echo "{} =>" $(realpath {})'

Upvotes: 1

Related Questions