I have multiple text files in a directory. At the end I want to append a string.
Eg. List of text files in directory.
Command to get their path:
find -name "*txt"
Then I tried to send
'echo "example text" > <filename>
So I tried running the following:
find -name "*txt" | xargs echo "example_text" >>
This command fails.
All I want to is append some text to the files every now and then and since the names of the files keep changing I wanted to use xargs
xargs
isn't really appropriate here. Maybe a loop over filenames like
for file in *.txt; do
echo "example_text" >>"$file"
done
Because >>
is a shell directive, if you want it honored via xargs, you need to have xargs start a shell. As Shawn's answer demonstrates, in many cases a shell glob is enough and you don't need find
at all; but if you do want to use find
, it can be used correctly either with or without xargs.
If you insist on using xargs
, even though it isn't the best tool for the job...
find . -name "*.txt" -print0 | xargs -0 sh -c '
for arg in "$@"; do echo "example_text" >>"$arg"; done
' _
Taking xargs
out, and just using find
(with -exec... {} +
to get the same performance benefits xargs
would otherwise offer):
find . -name "*.txt" -exec sh -c '
for arg in "$@"; do echo "example_text" >>"$arg"; done
' _ {} +
(in both of the above, the _
substitutes for $0
, so later arguments become $1
and later, and are thus iterated over when expanding "$@"
).
tee -a
! Un*x command tee
are built for this kind of operation and is a lot quicker!!
find . -type f -name '*.txt' -exec tee -a <<<'Foo bar baz' {} >/dev/null +
But herestring will work only if tee
are executed only once! (thanks to Charles Duffy's comment )!
See pure bash using globstar
further.
xargs
find . -type f -name '*.txt' -print0 |
xargs -0 sh -c 'echo "Foo bar baz"|tee -a "$@" >/dev/null ' _
find
really required?If all files are under same directory:
tee -a <<<'Foo bar baz' >/dev/null *.txt
Else, under [ŧag:bash], using globstar ( shopt -s globstar
):
tee -a <<<'Foo bar baz' >/dev/null **/*.txt
As many pointed out, xargs
is not appropriate, so you could just simply use find and pipe to read
in a loop to accomplish what you want easily as shown below.
find . -name "*.txt" | while read fname; do echo "example_text">>$fname; done
From the point of view of bash
, there are three parts in your command:
find -name "*txt"
)xargs echo "example_text"
)
) bash
tries to open the output file provided after the redirection but, as you didn't provided anything, bash
cannot open "nothing" and fails.
To solve your issue, you need to give xargs
a way to add the line you need to the file (without asking bash
to redirect the output of xargs
). A way that should work could be by starting a subshell that performs that operation:
find -name "*txt" | xargs -I{} bash -c 'echo "example_text" >> {}'
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.