Difference between revisions of "Find"
Line 79: | Line 79: | ||
Replace <code>-i.orig</code> with <code>-i</code> to suppress backups while still changing files in place. | Replace <code>-i.orig</code> with <code>-i</code> to suppress backups while still changing files in place. | ||
− | ===dos2unix/unix2dos== | + | ===dos2unix/unix2dos=== |
<syntaxhighlight lang=bash> | <syntaxhighlight lang=bash> |
Revision as of 07:02, 13 November 2015
Template:LowercaseTemplate:Unix
find is a unix program that lists files found recursively under a path.
Contents
Null-terminated output
See null-terminated (console).
Unsorted notes
Until I have time to properly document this, mess with it. Try some of the following:
# Lists files in and below your home directory find ~/
If the path to be searched is ".", that parameter can usually be omitted.
# Lists files in and below the current directory find . # or find
# Lists only the regular files (no dirs, symlinks, pipes, and so on) find . -type f
# Lists only the dirs find . -type d
# Lists regular files and symlinks find . -type f -o -type l # or, as a component to something more complex, find . \( -type f -o -type l \)
To run a command on each path found, use -exec. This example runs md5sum for all regular files (not symlinks, not directories, ...) in and below the current directory, if the read permissions are okay:
find . -type f -exec md5sum {} \; > ../MD5SUMS
The list of files can also be piped to xargs or perl; if using either one, use the -print0 condition on find to use null bytes as delimiters, then use the -0 switch on xargs or perl to expect the same.
# Use \0 as a delimiter instead of \n find . \( -type f -o -type l \) -print0 | perl -n -0 -E 'dosomethingwith($_)'
Using -exec
as a for-each mechanism
The predicate -exec
runs a command for each filename found. When in use, the -print
predicate is no longer implied. -exec
is used as such:
find ... -exec command [someargs] {} [otherargs] ';' ...
For every filename filename found, the command
command [someargs] filename [otherargs]
would be run. The {}
and the ';'
are not optional, while [someargs] and [otherargs] are optional.
Note that when passing arguments to an inline sh/bash script an extra argument should be used to fill the $0 argument if "$@" is being used:
find ... -exec sh -c 'echo "$@"' "$0" {} ';'
find and replace
Using sed:
find ... -exec sed -i.orig 's/PATTERN/REPLACEMENT/g' {} ';'
Using perl:
find ... -exec perl -p -i.orig -e 's/PATTERN/REPLACEMENT/g' {} ';'
Replace -i.orig
with -i
to suppress backups while still changing files in place.
dos2unix/unix2dos
find ... -exec dos2unix {} ';'
Call a shell function (bash only)
In bash (but not plain sh) we can export a bash function with export -f
and use it with -exec
via a special invocation of bash:
#!/bin/bash
# Define a function
somefunc() {
...
}
# Export the function to subshells
export -f somefunc
# Call from find
find ... -exec bash -c 'somefunc "$0"' {} ';'
Output relative URIs
Perl's URI::file knows how to convert a local file to a properly escaped URI.
find '...' -print0 | perl -0 -MURI::file -n -E 'chomp; say "".URI::file->new($_)'
Combining with Perl on the command line
Use perl's -0 switch to allow -print0 to be treated as lines.
This line prints file modified times ((stat(file))[9]
gets the mtime):
find -print0 | perl -n0e '$m=(stat("$_"))[9]; printf(q(%12s %s)."\n",$m,$_)'
You may also find my except-most-recent script handy if you find yourself writing a lot of backup rotation scripts.
See also
- xargs, which turns the output of this program into command line arguments.