Many sources say that every instance of {} will be replaced with the filename found through find, but when I try to run the following, I only get one text file and its name is ".txt"
find /directory -name "*pattern*" -exec cut -f8 {} > {}.txt \;
The goal was to create a text file with only the eighth column from each file found, and each text file will be named after its parent file. Something about that second set of {} is not replacing with the filename of each found file.
Find exec multiple commands syntaxThe -exec flag to find causes find to execute the given command once per file matched, and it will place the name of the file wherever you put the {} placeholder. The command must end with a semicolon, which has to be escaped from the shell, either as \; or as " ; ".
Try:
find /directory -name "*pattern*" -exec sh -c 'cut -f8 {} > {}.txt' \;
But be aware that some versions of find require {}
to be a distinct argument, and will not expand {}
to a filename otherwise. You can work around that with:
find /directory -name "*pattern*" -exec sh -c 'cut -f8 $0 > $0.txt' {} \;
(this alternate command will put the output file in the subdirectory which contains the matched file. If desired, you could avoid that by redirecting to ${0#*/}
The issue is that find
is not doing the redirection, the shell is. Your command is exactly equivalent to:
# Sample of INCORRECT code
find /directory -name "*pattern*" -exec cut -f8 {} \; > {}.txt
Note the following from the standard:
If more than one argument containing only the two characters "{}" is present, the behavior is unspecified.
If a utility_name or argument string contains the two characters "{}" , but not just the two characters "{}" , it is implementation-defined whether find replaces those two characters or uses the string without change.
To deal with the caveats that William Pursell mentioned in his answer, use the following:
find /directory -name "*pattern*" -exec sh -c 'cut -f8 "$1" > "$1.txt"' x {} \;
When you use sh -c
, it gets the positional parameters from arguments following the string to execute. The extra x
fills in $0
, and the substituted filename will become $1
.
The double quotes allow this to work properly with filenames containing spaces and other special characters.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With