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 -I[string]
, where [string]
is what you want to be replaced with the argument, in this case you'd use -I{}
, e.g. <strings.txt xargs -I{} grep {} directory/*
.
What you actually want to use is grep -F -f strings.txt
:
-F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated by
newlines, any of which is to be matched. (-F is specified by
POSIX.)
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file
contains zero patterns, and therefore matches nothing. (-f is
specified by POSIX.)
So grep -Ff strings.txt subdirectory/*
will find all occurrences of any string in strings.txt
as a literal, if you drop the -F
option you can use regular expressions in the file. You could actually use grep -F "$(<strings.txt)" directory/*
too. If you want to practice find
, you can use the last two examples in the summary. If you want to do a recursive search instead of just the first level, you have a few options, also in the summary.
Summary:
# grep for each string individually.
<strings.txt xargs -I{} grep {} directory/*
# grep once for everything
grep -Ff strings.txt subdirectory/*
grep -F "$(<strings.txt)" directory/*
# Same, using file
find subdirectory -maxdepth 1 -type f -exec grep -Ff strings.txt {} +
find subdirectory -maxdepth 1 -type f -print0 | xargs -0 grep -Ff strings.txt
# Recursively
grep -rFf strings.txt subdirectory
find subdirectory -type f -exec grep -Ff strings.txt {} +
find subdirectory -type f -print0 | xargs -0 grep -Ff strings.txt
You may want to use the -l
option to get just the name of each matching file if you don't need to see the actual line:
-l, --files-with-matches
Suppress normal output; instead print the name of each input
file from which output would normally have been printed. The
scanning will stop on the first match. (-l is specified by
POSIX.)
-r0
is two flags. It is -r
and it is -0
.
From the xargs(1)
manpage:
-r
If the standard input does not contain any nonblanks, do not run the command.
Normally, the command is run once even if there is no input. This option is a
GNU extension.
-0
Input items are terminated by a null character instead of by whitespace, and
the quotes and backslash are not special (every character is taken
literally). Disables the end of file string, which is treated like any other
argument. Useful when input items might contain white space, quote marks, or
backslashes. The GNU find -print0 option produces input suitable for this
mode.
Best Answer
Below are a dozen or so examples of how you can take a file such as this:
and convert it to this format:
You can use this command to create the above file if you'd like to play along:
The examples below are split into 2 groups. Ones that "work" and ones that "almost" work. I leave these because often times it's just as valuable to see why something doesn't work, as it is to see why something does.
Most scripting languages that I'm familiar with are represented. Some are represented multiple times, since as with the famous acronym typically referenced in Perl, TIMTOWTDI.
NOTE: You can swap out the comma (
,
) in the examples below and replace it with whatever characters you want, i.e.|
.Examples that "work"
These code snippets will produce the desired output.
The
paste
command:The
sed
command:The
perl
command:The
awk
command:The
python
command:Bash's
mapfile
built-in:The
ruby
command:The
php
command:Caveats
Most of the examples above will work just fine. Some have hidden issues, such as the PHP example above. The function
chop()
is actually an alias tortrim()
, so the last line's trailing spaces will also be removed.So too do does the first Ruby example, and the first Python example. The issue is with how they're all making use of a type of operation that essentially "chops" off, blindly, a trailing character. This is fine in for the example that the OP provided, but care must be taken when using these types of one liners to make sure that they conform with the data they're processing.
Example
Say our sample file,
k.txt
looked like this instead:It looks similar but it has one slight difference. It doesn't have a trailing newline (
\n
) like the original file. Now when we run the first Python example we get this:Examples that "almost" work
These are the "always a bridesmaid, never a bride" examples. Most of them could probably be adapted, but when working a potential solution to a problem, when it feels "forced", it's probably the wrong tool for the job!
The
perl
command:The
tr
command:The
cat
+echo
commands:The
ruby
command:Bash's
while
+read
built-ins: