Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use argument twice from standard output pipelining

I have a command line tool which receives two arguments:

TOOL  arg1 -o arg2

I would like to invoke it with the same argument provided it for arg1 and arg2, and to make that easy for me, i thought i would do:

each <arg1_value> | TOOL $1 -o $1

but that doesn't work, $1 is not replaced, but is added once to the end of the commandline.

An explicit example, performing:

cp fileA fileA

returns an error fileA and fileA are identical (not copied) While performing:

echo fileA | cp $1 $1

returns the following error: usage: cp [-R [-H | -L | -P]] [-fi | -n] [-apvX] source_file target_file cp [-R [-H | -L | -P]] [-fi | -n] [-apvX] source_file ... target_directory

any ideas?

like image 491
sramij Avatar asked Jun 22 '16 23:06

sramij


3 Answers

If you want to use xargs, the [-I] option may help:

-I replace-str
              Replace  occurrences of replace-str in the initial-arguments with names read from standard input.  Also, unquoted blanks do not terminate input items; instead the separa‐
              tor is the newline character.  Implies -x and -L 1.

Here is a simple example:

mkdir test && cd test && touch tmp
ls | xargs -I '{}' cp '{}' '{}'

Returns an Error cp: tmp and tmp are the same file

like image 161
Jiangty Avatar answered Sep 28 '22 08:09

Jiangty


The xargs utility will duplicate its input stream to replace all placeholders in its argument if you use the -I flag:

$ echo hello | xargs -I XXX echo XXX XXX XXX
hello hello hello

The placeholder XXX (may be any string) is replaced with the entire line of input from the input stream to xargs, so if we give it two lines:

$ printf "hello\nworld\n" | xargs -I XXX echo XXX XXX XXX
hello hello hello
world world world

You may use this with your tool:

$ generate_args | xargs -I XXX TOOL XXX -o XXX

Where generate_args is a script, command or shell function that generates arguments for your tool.

The reason

each <arg1_value> | TOOL $1 -o $1

did not work, apart from each not being a command that I recognise, is that $1 expands to the first positional parameter of the current shell or function.

The following would have worked:

set - "arg1_value"
TOOL "$1" -o "$1"

because that sets the value of $1 before calling you tool.

like image 31
Kusalananda Avatar answered Sep 28 '22 09:09

Kusalananda


You can re-run a shell to perform variable expansion, with sh -c. The -c takes an argument which is command to run in a shell, performing expansion. Next arguments of sh will be interpreted as $0, $1, and so on, to use in the -c. For example:

sh -c 'echo $1, i repeat: $1' foo bar baz will print execute echo $1, i repeat: $1 with $1 set to bar ($0 is set to foo and $2 to baz), finally printing bar, i repeat: bar

like image 27
λuser Avatar answered Sep 28 '22 08:09

λuser