Yes, you can use xargs
for this.
For example a simple:
$ locate commands.cfg | xargs grep check_dns
(When grep
sees multiple files it searches in each one and enables filename printing along matches.)
Or you can explicitly enable filename printing via:
$ locate commands.cfg | xargs grep -H check_dns
(Just in case one grep
is called only with 1 argument by xargs
)
For programs that only accept one filename argument (unlike grep
) you can restrict the number of supplied arguments like this:
$ locate commands.cfg | xargs -n1 grep check_dns
That does not print the names of files where matched lines are from.
The result is equivalent to:
$ locate commands.cfg | xargs grep -h check_dns
With a modern locate/xargs you can also protect against whitespace issues:
$ locate -0 commands.cfg | xargs -0 grep -H check_dns
(By default whitespace separates input of xargs
- which is of course a problem when your filenames contain whitespace ...)
With GNU find (on Linux or Cygwin), you can look for files whose relative path is more than 255 characters long:
find -regextype posix-extended -regex '.{257,}'
(257 accounts for the initial ./
.)
Best Answer
(Read on for the main terms and conditions. Read the manual for the fine print.)
Listing the contents of a directory is kind of a secondary feature of
ls
. The main job ofls
, the one that takes up most of its complexity, is fine-tuning its display. (Look at the manual and compare the number of options related to choosing what files to display vs. the number of options that control what information to display about each file and how the display is formatted. This is true both of GNU ls which you'll find on Linux, and of other systems with fewer options, since the early days.)The default mode of
ls
is that when you pass it a directory, it lists the files in that directory. If you pass it any other type of file (regular file, symbolic link, etc.), it lists just that file. (This applies to each argument separately.) The option-d
tellsls
never to descend into a directory.ls
does have an option-R
that tells it to list directories recursively. But it's of limited applicability, and doesn't allow much filtering on the output.The very first tool to perform pattern matching is the shell itself. You don't need any other command: just type your wildcards and you're set. This is known as globbing.
Traditionally, wildcards were limited to the current directory (or the indicated directory:
echo /some/where/*filename*
). A*
matches any file name, or any portion of file name, but*.txt
will not matchfoo/bar.txt
. Modern shells have added the pattern**/
which means “in this directory, or in any directory below it (recursively)”. With bash, for historical compatibility reasons, this feature needs to be explicitly enabled withshopt -s globstar
(you can put this line in your~/.bashrc
).The
echo
command just echoes the list of file names generated by the shell back at you. As an exception, if there is no matching file name at all, the wildcard pattern is left unchanged in bash (unless you setshopt -s nullglob
, in which case the pattern expands to an empty list), and zsh signals an error (unless you setsetopt nullglob
, orsetopt no_no_match
which causes the pattern to be left unchanged).You may still want to use
ls
for its options. For example,ls
can give indications about the nature or permissions of the file (directory, executable, etc.) through colors. You may want to display the file's date, size and ownership withls -l
. See the manual for many more options.The traditional command to look for a file in a directory tree is
find
. It comes with many options to control which files to display and what to do with them. For example, to look for files whose name matches the pattern*filename*
in the current directory and its subdirectories and print their names:-print
is an action (most other actions consist of executing a command on the file); if you don't put an action,-print
is implied. Also, if you don't specify any directory to traverse (/some/dir
above), the current directory is implied. The condition-name '*filename'
says to list (or act on) only the files whose name matches that pattern; there are many other filters, such as-mtime -1
to match the files modified in the last 24 hours. You can sometimes omit the quotes on-name '*filename*'
, but only if the wildcard would not match any file in the current directory (see above). All in all, the short form isAnother useful tool when you know (part of) the name of a file is
locate
. This tool queries a database of file names. On typical systems, it's refreshed every night. The advantage oflocate
overfind /
is that it's a lot faster. A downside is that its information may be stale. There are several implementations oflocate
which differ in their behavior on multi-user systems: the basiclocate
program indexes only publicly-readable files (you may want to run the companionupdatedb
to make a second database that indexes all the files in your account); there are other versions (mlocate, slocate) that index all files and have thelocate
program filter the database to only return the files you can see.Sometimes you think that a file is provided by a package in your distribution, you know (part of) the name of the file but not the name of your package, and you'd like to install the package. Many distributions provide a tool for that. On Ubuntu, it's
apt-file search filename
. For equivalent commands on other systems, check the Pacman Rosetta.