Reputation: 8173
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
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
Reputation: 107759
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
Reputation: 15501
Alternatively:
find /usr/lib -maxdepth 1 -type l \
-exec echo -n '{} =>' \; \
-exec realpath '{}' \;
Upvotes: 4
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
Reputation: 39581
Have xargs call the shell:
find /usr/lib -maxdepth 1 -type l -iname "*libblas*"|xargs -I{} sh -c 'echo "{} =>" $(realpath {})'
Upvotes: 1