Hot answers tagged

76

The difference is in what data the target program is accepting. If you just use a pipe, it receives data on STDIN (the standard input stream) as a raw pile of data that it can sort through one line at a time. However some programs don't accept their commands on standard in, they expect it to be spelled out in the arguments to the command. For example touch ...


44

To expand on the answers already provided, some xargs implementations (like GNU or modern BSDs) can do one cool thing that is becoming increasingly important in today's multicore and distributed computing landscape: it can parallel process jobs. For example: $ find . -type f -name '*.wav' -print0 |xargs -0 -P 3 -n 1 flac -V8 will encode *.wav => *.flac, ...


41

Michael's answer is right, and should sort out your problem. Running cat file | xargs -I % curl http://example.com/persons/%.tar will download files bob.tar john.tar. sue.tar as expected. BUT: cat here is useless rather use: <file xargs -I % curl http://example.com/persons/%.tar


35

Some versions of sort have a -z option, which allows for null-terminated records. find folder1 folder2 -name "*.txt" -print0 | sort -z | xargs -r0 myCommand Additionally, you could also write a high-level script to do it: find folder1 folder2 -name "*.txt" -print0 | python -c 'import sys; sys.stdout.write("\0".join(sorted(sys.stdin.read().split("\0"))))' ...


25

You can just use standard globbing on the rm command: rm -- *\ * This will delete any file whose name contains a space; the space is escaped so the shell doesn't interpret it as a separator. Adding -- will avoid problems with filenames starting with dashes (they won't be interpreted as arguments by rm). If you want to confirm each file before it's ...


20

First of all, do not use ls output as a file list. Use shell expansion or find. See below for potential consequences of ls+xargs misuse and an example of proper xargs usage. 1. Simple way: for loop If you want to process just the files under A/, then a simple for loop should be enough: for file in A/*.dat; do ./a.out < "$file" > "${file%.dat}.ans"; ...


19

No, you can't. From the xargs sources at savannah.gnu.org: if (WEXITSTATUS (status) == CHILD_EXIT_PLEASE_STOP_IMMEDIATELY) error (XARGS_EXIT_CLIENT_EXIT_255, 0, _("%s: exited with status 255; aborting"), bc_state.cmd_argv[0]); if (WIFSTOPPED (status)) error (XARGS_EXIT_CLIENT_FATAL_SIG, 0, _("%s: stopped by signal %d"), ...


18

Simply keep it within the realm of find: find . -type f -exec grep "something" {} \; -quit This is how it works: The -exec will work when the -type f will be true. And because grep returns 0 (success/true) when the -exec grep "something" has a match, the -quit will be triggered.


16

Summary: If there ever was a shell that expanded {}, it's really old legacy stuff by now. In the Bourne shell and in POSIX-compliant shells, braces ({ and }) are ordinary characters (unlike ( and ) which are word delimiters like ; and &, and [ and ] which are globbing characters). The following strings are all supposed to be printed literally: $ echo { ...


15

The history command just operates on your history file, $HISTFILE (typically ~/.history or ~/.bash_history). It'll be much easier if you just remove the lines from that file, which can be done many ways. grep is one way, but you have to be careful not to overwrite the file while still reading it: $ grep -v searchstring "$HISTFILE" > /tmp/history $ mv ...


15

Just swap \0 and \n: find ... -print0 | tr '\0\n' '\n\0' | head | tr '\0\n' '\n\0' Note that some head implementations can't cope with NUL characters (and they're not required to by POSIX), but where find supports -print0, head and text utilities generally support NUL characters. You can also use a function to wrap any command between the two trs: ...


14

If I understand correctly, you want to fire up one instance flac … | lame … for each input line, and interpolate the input into the arguments to both commands. Since you need xargs to start a pipeline, you need to make it start a program that's capable of creating pipelines, i.e. a shell. inotifywait -m -r -q -e moved_to --format "%w%f" ~/test | xargs -l ...


14

Safely piping file names to xargs requires that your find supports the -print0 option and your xargs has the corresponding option to read it (--null or -0). Otherwise, filenames with unprintable characters or backslashes or quotes or whitespace in the name may cause unexpected behavior. On the other hand, find -exec {} + is in the POSIX find spec, so it is ...


14

The shell is expanding the >> % part before xargs sees it. If you need to do shell redirections, you'll have to try something like this: find . -name "*.txt" -exec sh -c ' echo "hello world" >> "$0" ' {} \; How it works: find replaces {} with each file that it matches bash -c "some command" arg0... sets $0... inside the "some ...


14

Normally xargs will put several arguments on one command line. To limit it to one argument at a time, use the -n option: $ seq 3 | xargs -n 1 echo 1 2 3 Documentation From man xargs: -n max-args Use at most max-args arguments per command line. Fewer than max-args arguments will be used if the size (see the -s ...


13

This can be done from find directly using -exec: find . -name "*.xml" -type f -exec xmllint --output '{}' --format '{}' \; Whats passed to -exec will be invoked once per file found with the template parameters {} being replaced with the current file name. The \; on the end of the find command just terminates the line. The use of xargs isn't really ...


13

xargs is particularly useful when you have a list of filepaths on stdin and want to do something with them. For example: $ git ls-files "*.tex" | xargs -n 1 sed -i "s/color/colour/g" Let's examine this step by step: $ git ls-files "*.tex" tex/ch1/intro.tex tex/ch1/motivation.tex .... In other words, our input is a list of paths that we want to do ...


13

Look at Stephane's answer for the best method, take a look at my answer for reasons not to use the more obvious solutions (and reasons why they are not the most efficient). You can use the -I option of xargs: find /tmp/ -ctime -1 -name "x*" | xargs -I '{}' mv '{}' ~/play/ Which works in a similar mechanism to find and {}. I would also quote your -name ...


13

Yes it can, with the unimaginatively named cat command: $ cat *csv > all.csv cat does what it says on the bottle, it conCATenates its input and prints to standard output. The command above will give an error if a file called all.csv already exists in the target directory: $ cat *csv > all.csv cat: all.csv: input file is output file You can safely ...


12

Below are a dozen or so examples of how you can take a file such as this: $ cat k.txt 1 2 3 and convert it to this format: 1,2,3 You can use this command to create the above file if you'd like to play along: $ cat <<EOF > k.txt 1 2 3 EOF The examples below are split into 2 groups. Ones that "work" and ones that "almost" work. I leave these ...


12

Yes, find ./work -print0 | xargs -0 rm will execute something like rm ./work/a "work/b c" .... You can check with echo, find ./work -print0 | xargs -0 echo rm will print the command that will be executed (except white space will be escaped appropriately, though the echo won't show that). To get xargs to put the names in the middle, you need to add ...


12

I think you're asking how to insert the individual lines pulled from xargs' stdin in the middle of a command, instead of just pasting it on the end always. If so, the -I flag takes a replacement-string argument; xargs will then replace replacement-string in the command with the line read from stdin: $ cat file | xargs -I foobar curl ...


12

You might want to chain calls to find (once, when you learned, that it is possible, which might be today). This is of course only possible as long as you stay in find. Once you pipe to xargs, it's out of scope. Small example, two files a.lst and b.lst: cat a.lst fuddel.sh fiddel.sh cat b.lst fuddel.sh No trick here - simply the fact that both contain ...


12

You can prevent the file from reaching xargs using: find . -maxdepth 1 -type f ! -name sums.sha1 -printf '%P\n' | xargs -r shasum -- > sums.sha1 To prevent problems with filename that have blanks or newlines or quotes or backslashes, I would however use: find . -maxdepth 1 -type f ! -name sums.sha1 -printf '%P\0' | xargs -r0 shasum -- > ...


11

The [bash] man page says: "-c string If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0." - The key is $0; it means that the command name shall be the first argument. seq 10 | xargs sh -c 'echo $@; echo $0' sh 1 2 3 4 5 6 7 8 9 10 sh


11

GNU Parallel is specifcally designed to solve this problem: echo -n $IPs | parallel -d ' ' -j0 wget -q -O- http://{}/somepage.html | egrep --count '^string' If your IPs are in a file it is even prettier: cat IPs | parallel -j0 wget -q -O- http://{}/somepage.html | egrep --count '^string' To learn more watch the intro video: ...


11

The second example: find . -name '*.txt' -print0 | xargs -0 cat > out.txt Is completely legal and will recreate the file, out.txt each time it's run, while the first will concatenate to out.txt if it runs. But both commands are doing essentially the same thing. What's confusing the issue is the xargs -0 cat. People think that the redirect to out.txt ...


11

Because Vim is invoked from inside the pipeline, the stdin is connected to the previous pipeline's output, not the terminal. As an interactive command, Vim needs to receive its input from the terminal. Better avoid the pipe, e.g. via $ vim $(grep -rl test .) or from inside Vim: :args `grep -rl test .`


11

You can simply use xargs xsel | xargs -n1 echo mycommand -n1 means one arg for mycommand, but it's just dry run, it will show what going to be run, to run it remove echo For constant Argument xsel | xargs -I {} -n1 echo mycommand "constantArgument" {}


10

If you want that last 10 lines: tail myFile.txt | tr '\n' '\0' | xargs -r0i myCmd {} arg1 arg2 But with GNU xargs, you can also set the delimiter to newline with: tail myFile.txt | xargs -r0i -d '\n' myCmd {} arg1 arg2 (-0 is short for -d '\0'). Portably, you can also simply escape every character: tail myFile.txt | sed 's/./\\&/g' | xargs -I{} ...



Only top voted, non community-wiki answers of a minimum length are eligible