xargs
A filter for feeding arguments to a command, and also a tool for assembling the commands themselves. It breaks a data stream into small enough chunks for filters and commands to process. Consider it as a powerful replacement for backquotes. In situations where backquotes fail with a too many arguments error, substituting xargs often works. Normally, xargs reads from stdin or from a pipe, but it can also be given the output of a file.
The default command for xargs is echo. This means that input piped to xargs may have linefeeds and other whitespace characters stripped out.
bash$ ls -l
total 0
-rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file1
-rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file2
bash$ ls -l | xargs
total 0 -rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file1 -rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file2
total 0
-rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file1
-rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file2
bash$ ls -l | xargs
total 0 -rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file1 -rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file2
ls | xargs -p -l gzip gzips every file in current directory, one at a time, prompting before each operation.
An interesting xargs option is -n NN, which limits to NN the number of arguments passed. ls | xargs -n 8 echo lists the files in the current directory in 8 columns. |
Another useful option is -0, in combination with find -print0 or grep -lZ. This allows handling arguments containing whitespace or quotes. find / -type f -print0 | xargs -0 grep -liwZ GUI | xargs -0 rm -f grep -rliwZ GUI / | xargs -0 rm -f Either of the above will remove any file containing "GUI". (Thanks, S.C.) |
Example 12-4. Logfile using xargs to monitor system log
1 #!/bin/bash
2
3 # Generates a log file in current directory
4 # from the tail end of /var/log/messages.
5
6 # Note: /var/log/messages must be world readable
7 # if this script invoked by an ordinary user.
8 # #root chmod 644 /var/log/messages
9
10 LINES=5
11
12 ( date; uname -a ) >>logfile
13 # Time and machine name
14 echo --------------------------------------------------------------------- >>logfile
15 tail -$LINES /var/log/messages | xargs | fmt -s >>logfile
16 echo >>logfile
17 echo >>logfile
18
19 exit 0
20
21 # Exercise:
22 # --------
23 # Modify this script to track changes in /var/log/messages at intervals
24 #+ of 20 minutes.
25 # Hint: Use the "watch" command.
2
3 # Generates a log file in current directory
4 # from the tail end of /var/log/messages.
5
6 # Note: /var/log/messages must be world readable
7 # if this script invoked by an ordinary user.
8 # #root chmod 644 /var/log/messages
9
10 LINES=5
11
12 ( date; uname -a ) >>logfile
13 # Time and machine name
14 echo --------------------------------------------------------------------- >>logfile
15 tail -$LINES /var/log/messages | xargs | fmt -s >>logfile
16 echo >>logfile
17 echo >>logfile
18
19 exit 0
20
21 # Exercise:
22 # --------
23 # Modify this script to track changes in /var/log/messages at intervals
24 #+ of 20 minutes.
25 # Hint: Use the "watch" command.
Example 12-5. copydir, copying files in current directory to another, using xargs
1 #!/bin/bash
2
3 # Copy (verbose) all files in current directory
4 # to directory specified on command line.
5
6 if [ -z "$1" ] # Exit if no argument given.
7 then
8 echo "Usage: `basename $0` directory-to-copy-to"
9 exit 65
10 fi
11
12 ls . | xargs -i -t cp ./{} $1
13 # This is the exact equivalent of
14 # cp * $1
15 # unless any of the filenames has "whitespace" characters.
16
17 exit 0
2
3 # Copy (verbose) all files in current directory
4 # to directory specified on command line.
5
6 if [ -z "$1" ] # Exit if no argument given.
7 then
8 echo "Usage: `basename $0` directory-to-copy-to"
9 exit 65
10 fi
11
12 ls . | xargs -i -t cp ./{} $1
13 # This is the exact equivalent of
14 # cp * $1
15 # unless any of the filenames has "whitespace" characters.
16
17 exit 0
No comments:
Post a Comment