This is what I tried:
find . -name *.sv | xargs sed -i -e '<command>' -e '<command>'
It does not work. Using the exact same command on each file still works.
Thanks for the help.
This is what I tried:
find . -name *.sv | xargs sed -i -e '<command>' -e '<command>'
It does not work. Using the exact same command on each file still works.
Thanks for the help.
To force xargs to only execute sed with a single file at a time, use -n 1 with xargs. You should also pass the pathnames from find using -print0 and get xargs to receive them with -0 (if your find and xargs supports these nonstandard options), so that pathnames containing spaces etc. are handled correctly. You probably also need to specify that you are looking for regular files (and not directories etc.) and you definitely need to quote that shell glob (or it may expand to any matching filename in the current directory):
find . -type f -name '*.sv' -print0 | xargs -0 -n 1 sed -i -e '<command>' -e '<command>'
Or, just use find:
find . -type f -name '*.sv' -exec sed -i -e '<command>' -e '<command>' {} ';'
Related:
A solution that is not using find, but instead uses the ** globbing pattern (matches "recursively" down into subdirectories) available in bash after doing shopt -s globstar:
shopt -s globstar dotglob nullglob
for pathname in ./**/*.sv; do
if [[ -f "$pathname" ]] && [[ ! -h "$pathname" ]]; then
sed -i -e '<command> -e '<command>' "$pathname"
fi
done
This loop loops over all files that have a filename suffix .sv and tests whether each matched name is a regular file (we have to test separately with ! -h to make sure its not a symbolic link to a regular file) before applying the sed command. The shell options enable the use of ** (globstar), matching of hidden names (dotglob), and removes the patterns completely if it does not match (nullglob).
Or, with the zsh shell, which has ** enabled by default, and can use a "glob qualifier" to do most of the "extra" work that bash has to do explicitly:
for pathname in ./**/.sv(.DN); do
sed -i -e '<command> -e '<command>' "$pathname"
done
The glob qualifier (.DN) modifies the preceding globbing pattern so that it matches only regular files, matches hidden names, and expands to nothing if there is no match at all.
-i imply -s (i.e. that sed will treat the files as separate, even if xargs doesn't)?
– steeldriver
Jun 05 '18 at 19:15
sed very often (and never with -i). The original command may still have issues with whitespace in file names though (and the other issues).
– Kusalananda
Jun 05 '18 at 19:31
-e options on the sed. -e denotes a sed script will follow, not a sed command. sed -e '<command1> ; <command2>' FILE works just fine.
– Centimane
Jun 06 '18 at 10:25
-e denotes that the following argument is a sed expression or command. -f is used to read a script from a file. There is no benefit to combining the arguments of several -e into a single string, and in some cases, it's even impossible to do so.
– Kusalananda
Jun 06 '18 at 11:12
-e denotes a script as per the man page: "add the script to the commands to be executed". I don't think there are any cases where it's impossible, you just might have to escape some characters if using double-quotes instead of single. It is true though that the result is the same, but it's good to recognize that -e is for passing a script rather than a single command.
– Centimane
Jun 06 '18 at 11:48
script but calls it "the editing commands", so I think we may both call ourselves correct on that point. If you want to use the sed command a or i, it's nice looking to use -e 'i\' -e 'text' than to embed a newline in the single quoted string. Regardless of all of this, whether one or several -e is used (or none) is totally unimportant to this question.
– Kusalananda
Jun 06 '18 at 12:03
Here is another method that worked for me:
find -name "*.fail" | xargs -L 1 sed -i -e 's/cse/ecs/g' -e 's/trex/dino/g'