Tag Info

Hot answers tagged

57

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 ...


35

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, ...


29

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


17

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"))))' ...


16

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"), ...


15

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"; ...


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 ...


13

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.


12

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 { ...


12

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 ...


12

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: ...


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

Is using find or xargs mandatory? If not, you can use: chmod -R u=rwX,go=rX *


10

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 ...


10

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 ...


10

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 ...


10

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 ...


9

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: ...


9

To act on multiple files at once with find, use + instead of \;: find . -name '*.foo' -exec gedit {} + With zsh, or with bash ≥4 if you put shopt -s globstar in your ~/.bashrc, you can use **/ to recurse into subdirectories: gedit **/*.foo Zsh also has many glob qualifiers which can replace most uses of find.


9

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 ...


9

I guess you mean the first option grep recursive, for searching content inside files grep -R "content_to_search" /path/to/directory ls recursive, for searching files that match ls -lR | grep "your_search"


9

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 ...


9

If your search results are sure to return paths with no spaces, you could use xargs like this: locate my.cnf | xargs grep user However you should get in the habit of protecting yourself to handle the case where a path or filename might contain a space by telling xargs to use null as a separator and telling locate (or whatever program you are using to ...


9

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 ...


8

A more general solution would be sudo apt-get remove `cat packages` where you will have a problem if the list of packages is really long. The reason that it isn't working is that apt-get is trying to read your confirmation from the standard input which - because of the pipe - is attached to cat. Contrariwise, sudo does the Right Thing by asking your ...


8

try this. should work with recent versions of xargs. svn st | awk '{print $2}' | xargs -iz scp z my_name@my_server: alternately, you could just loop though the files. for file in $(svn st | awk '{print $2}'); do scp $file my_name@my_server: ; done


8

It needs to be like this: ls | xargs touch The xargs command runs the touch command with a number of strings read from stdin. In your case, stdin for xargs is the output end of the pipe from ls. The way you had the command: ls | xargs | touch xargs had no command to run against the strings (filenames) it would read from stdin. In that case, xargs ...


8

Remove the -L 1; it is implied by -I (as the man page says), but it would override it when specified afterwards.


8

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 ...


8

You need an -r or --no-run-if-empty options. Keep in mind that this particular behavior is hard to make cross-platform. BSD versions of xargs run with -r by default. GNU version needs it. FreeBSD version of xargs ignores -r flag for compatibility with GNU. Mac OS X version does not even accept the flag and throws an error illegal option. You might then ...



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