|
Go to the previous, next chapter.
There are several ways you can print information about the
files that match the criteria you gave in the find
expression. You can print the information either to the standard
output or to a file that you name. You can also execute commands
that have the file names as arguments. You can use those commands
as further filters to select files.
- Action: -print True; print the full file name on the
standard output, followed by a newline.
- Action: -fprint file True; print the full file name into
file file, followed by a newline. If file
does not exist when find is run, it is created; if
it does exist, it is truncated to 0 bytes. The file names /dev/stdout
and /dev/stderr are handled specially; they refer to the
standard output and standard error output, respectively.
- Action: -ls True; list the current file in ls -dils
format on the standard output. The output looks like this:
204744 17 -rw-r--r-- 1 djm staff 17337 Nov 2 1992 ./lwall-quotes
The fields are:
- The inode number of the file. See section Hard Links, for how to find
files based on their inode number.
- the number of blocks in the file. The block counts are of
1K blocks, unless the environment variable
POSIXLY_CORRECT
is set, in which case 512-byte blocks are used. See
section Size, for how to
find files based on their size.
- The file's type and permissions. The type is shown as a
dash for a regular file; for other file types, a letter
like for -type is used (see section Type). The permissions are
read, write, and execute for the file's owner, its group,
and other users, respectively; a dash means the
permission is not granted. See section File Permissions, for more
details about file permissions. See section Permissions, for how to find
files based on their permissions.
- The number of hard links to the file.
- The user who owns the file.
- The file's group.
- The file's size in bytes.
- The date the file was last modified.
- The file's name. -ls quotes non-printable
characters in the file names using C-like backslash
escapes.
- Action: -fls file True; like -ls but write to file
like -fprint (see section Print
File Name).
- Action: -printf format True; print format on the
standard output, interpreting \ escapes and %
directives. Field widths and precisions can be specified as with
the printf C function. Unlike -print, -printf
does not add a newline at the end of the string.
- Action: -fprintf file format True; like -printf
but write to file like -fprint (see
section Print File Name).
The escapes that -printf and -fprintf
recognize are:
- \a Alarm bell. \b Backspace. \c Stop
printing from this format immediately and flush the
output. \f Form feed. \n Newline. \r
Carriage return. \t Horizontal tab. \v
Vertical tab. \\ A literal backslash (\).
A \ character followed by any other character is
treated as an ordinary character, so they both are printed, and a
warning message is printed to the standard error output (because
it was probably a typo).
-printf and -fprintf support the
following format directives to print information about the file
being processed. Unlike the C printf function, they
do not support field width specifiers.
%% is a literal percent sign. A %
character followed by any other character is discarded (but the
other character is printed), and a warning message is printed to
the standard error output (because it was probably a typo).
- %p File's name. %f File's name with any
leading directories removed (only the last element). %h
Leading directories of file's name (all but the last
element and the slash before it). %P File's name
with the name of the command line argument under which it
was found removed from the beginning. %H Command
line argument under which file was found.
- %g File's group name, or numeric group ID if the
group has no name. %G File's numeric group ID. %u
File's user name, or numeric user ID if the user has no
name. %U File's numeric user ID. %m File's
permissions (in octal).
- %k File's size in 1K blocks (rounded up). %b
File's size in 512-byte blocks (rounded up). %s
File's size in bytes.
- %d File's depth in the directory tree; files named
on the command line have a depth of 0. %F Type of
the filesystem the file is on; this value can be used for -fstype
(see section Directories). %l
Object of symbolic link (empty string if file is not a
symbolic link). %i File's inode number (in
decimal). %n Number of hard links to file.
Some of these directives use the C ctime
function. Its output depends on the current locale, but it
typically looks like
Wed Nov 2 00:42:36 1994
- %a File's last access time in the format returned
by the C
ctime function. %Ak
File's last access time in the format specified by k
(see section Time Formats). %c
File's last status change time in the format returned by
the C ctime function. %Ck
File's last status change time in the format specified by k
(see section Time Formats). %t
File's last modification time in the format returned by
the C ctime function. %Tk
File's last modification time in the format specified by k
(see section Time Formats).
Below are the formats for the directives %A, %C,
and %T, which print the file's timestamps. Some of
these formats might not be available on all systems, due to
differences in the C strftime function between
systems.
The following format directives print single components of the
time.
- H hour (00..23) I hour (01..12) k
hour ( 0..23) l hour ( 1..12) p locale's AM
or PM Z time zone (e.g., EDT), or nothing if no
time zone is determinable M minute (00..59) S
second (00..61) @ seconds since Jan. 1, 1970,
00:00 GMT.
The following format directives print single components of the
date.
- a locale's abbreviated weekday name (Sun..Sat) A
locale's full weekday name, variable length
(Sunday..Saturday) b h locale's abbreviated
month name (Jan..Dec) B locale's full month name,
variable length (January..December) m month
(01..12) d day of month (01..31) w day of
week (0..6) j day of year (001..366) U week
number of year with Sunday as first day of week (00..53) W
week number of year with Monday as first day of week
(00..53) Y year (1970...) y last two digits
of year (00..99)
The following format directives print combinations of time and
date components.
- r time, 12-hour (hh:mm:ss [AP]M) T time,
24-hour (hh:mm:ss) X locale's time representation
(H:M:S) c locale's date and time (Sat Nov 04
12:02:33 EST 1989) D date (mm/dd/yy) x
locale's date representation (mm/dd/yy)
You can use the list of file names created by find
or locate as arguments to other commands. In this
way you can perform arbitrary actions on the files.
Here is how to run a command on one file at a time.
- Action: -exec command ; Execute command; true if
0 status is returned. find takes all arguments after -exec
to be part of the command until an argument consisting of ;
is reached. It replaces the string {} by the current
file name being processed everywhere it occurs in the command.
Both of these constructions need to be escaped (with a \)
or quoted to protect them from expansion by the shell. The
command is executed in the directory in which find
was run.
For example, to compare each C header file in the current
directory with the file /tmp/master:
find . -name '*.h' -exec diff -u '{}' /tmp/master ';'
Sometimes you need to process files alone. But when you don't,
it is faster to run a command on as many files as possible at a
time, rather than once per file. Doing this saves on the time it
takes to start up the command each time.
To run a command on more than one file at once, use the xargs
command, which is invoked like this:
xargs [option...] [command [initial-arguments]]
xargs reads arguments from the standard input,
delimited by blanks (which can be protected with double or single
quotes or a backslash) or newlines. It executes the command
(default is /bin/echo) one or more times with any initial-arguments
followed by arguments read from standard input. Blank lines on
the standard input are ignored.
Instead of blank-delimited names, it is safer to use find
-print0 or find -fprint0 and process the
output by giving the -0 or --null
option to GNU xargs, GNU tar, GNU cpio,
or perl.
You can use shell command substitution (backquotes) to process
a list of arguments, like this:
grep -l sprintf `find $HOME -name '*.c' -print`
However, that method produces an error if the length of the .c
file names exceeds the operating system's command-line length
limit. xargs avoids that problem by running the
command as many times as necessary without exceeding the limit:
find $HOME -name '*.c' -print | grep -l sprintf
However, if the command needs to have its standard input be a
terminal (less, for example), you have to use the
shell command substitution method.
Because file names can contain quotes, backslashes, blank
characters, and even newlines, it is not safe to process them
using xargs in its default mode of operation. But
since most files' names do not contain blanks, this problem
occurs only infrequently. If you are only searching through files
that you know have safe names, then you need not be concerned
about it.
In many applications, if xargs botches processing
a file because its name contains special characters, some data
might be lost. The importance of this problem depends on the
importance of the data and whether anyone notices the loss soon
enough to correct it. However, here is an extreme example of the
problems that using blank-delimited names can cause. If the
following command is run daily from cron, then any
user can remove any file on the system:
find / -name '#*' -atime +7 -print | xargs rm
For example, you could do something like this:
eg$ echo > '#
vmunix'
and then cron would delete /vmunix, if
it ran xargs with / as its current
directory.
To delete other files, for example /u/joeuser/.plan,
you could do this:
eg$ mkdir '#
'
eg$ cd '#
'
eg$ mkdir u u/joeuser u/joeuser/.plan'
'
eg$ echo > u/joeuser/.plan'
/#foo'
eg$ cd ..
eg$ find . -name '#*' -print | xargs echo
./# ./# /u/joeuser/.plan /#foo
Here is how to make find output file names so
that they can be used by other programs without being mangled or
misinterpreted. You can process file names generated this way by
giving the -0 or --null option to GNU xargs,
GNU tar, GNU cpio, or perl.
- Action: -print0 True; print the full file name on the
standard output, followed by a null character.
- Action: -fprint0 file True; like -print0 but
write to file like -fprint (see section Print File Name).
xargs gives you control over how many arguments
it passes to the command each time it executes it. By default, it
uses up to ARG_MAX - 2k, or 20k, whichever is
smaller, characters per command. It uses as many lines and
arguments as fit within that limit. The following options modify
those values.
- --no-run-if-empty -r If the standard input
does not contain any nonblanks, do not run the command.
By default, the command is run once even if there is no
input.
--max-lines[=max-lines] -l[max-lines]
Use at most max-lines nonblank input lines per
command line; max-lines defaults to 1 if
omitted. Trailing blanks cause an input line to be
logically continued on the next input line, for the
purpose of counting the lines. Implies -x.
--max-args=max-args -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 option) is
exceeded, unless the -x option is given, in
which case xargs will exit.
--max-chars=max-chars -s max-chars
Use at most max-chars characters per command
line, including the command and initial arguments and the
terminating nulls at the ends of the argument strings.
--max-procs=max-procs -P max-procs
Run up to max-procs processes at a time; the
default is 1. If max-procs is 0, xargs
will run as many processes as possible at a time. Use the -n, -s,
or -l option with -P; otherwise
chances are that the command will be run only once.
xargs can insert the name of the file it is
processing between arguments you give for the command. Unless you
also give options to limit the command size (see section Limiting Command Size), this mode of
operation is equivalent to find -exec (see section Single File).
- --replace[=replace-str] -i[replace-str]
Replace occurences of replace-str in the
initial arguments with names read from standard input.
Also, unquoted blanks do not terminate arguments. If replace-str
is omitted, it defaults to {} (like for find
-exec). Implies -x and -l 1.
As an example, to sort each file the bills
directory, leaving the output in that file name with .sorted
appended, you could do:
-
find bills -type f | xargs -iXX sort -o XX.sorted XX
The equivalent command using find -exec
is:
find bills -type f -exec sort -o '{}.sorted' '{}' ';'
To ask the user whether to execute a command on a single file,
you can use the find primary -ok
instead of -exec:
- Action: -ok COMMAND ; Like -exec (see section Single File), but ask the user first
(on the standard input); if the response does not start with y
or Y, do not run the command, and return false.
When processing multiple files with a single command, to query
the user you give xargs the following option. When
using this option, you might find it useful to control the number
of files processed per invocation of the command (see section Limiting Command Size).
- --interactive -p Prompt the user about
whether to run each command line and read a line from the
terminal. Only run the command line if the response
starts with y or Y. Implies -t.
You can test for file attributes that none of the find
builtin tests check. To do this, use xargs to run a
program that filters a list of files printed by find.
If possible, use find builtin tests to pare down the
list, so the program run by xargs has less work to
do. The tests builtin to find will likely run faster
than tests that other programs perform.
For example, here is a way to print the names of all of the
unstripped binaries in the /usr/local directory tree.
Builtin tests avoid running file on files that are
not regular files or are not executable.
find /usr/local -type f -perm +a=x | xargs file |
grep 'not stripped' | cut -d: -f1
The cut program removes everything after the file
name from the output of file.
If you want to place a special test somewhere in the middle of
a find expression, you can use -exec to
run a program that performs the test. Because -exec
evaluates to the exit status of the executed program, you can
write a program (which can be a shell script) that tests for a
special attribute and make it exit with a true (zero) or false
(non-zero) status. It is a good idea to place such a special test after
the builtin tests, because it starts a new process which could be
avoided if a builtin test evaluates to false. Use this method
only when xargs is not flexible enough, because
starting one or more new processes to test each file is slower
than using xargs to start one process that tests
many files.
Here is a shell script called unstripped that
checks whether its argument is an unstripped binary file:
#!/bin/sh
file $1 | grep 'not stripped' > /dev/null
This script relies on the fact that the shell exits with the
status of the last program it executed, in this case grep. grep
exits with a true status if it found any matches, false if not.
Here is an example of using the script (assuming it is in your
search path). It lists the stripped executables in the file sbins
and the unstripped ones in ubins.
find /usr/local -type f -perm +a=x \
\( -exec unstripped '{}' \; -fprint ubins -o -fprint sbins \)
To return to the Ready-to-Run Software Win95Pak Table of Contents please press here.
|