There are a few issues with the code and input file in this question:
The input file obviously have trailing carriage returns (\r
) on each line. This is probably due to hit having been created on a Windows machine as a DOS text file. The usual way to get rid of these carriage returns is to run dos2unix
on the file. See, for example, the question What is `^M` and how do I get rid of it?
All variable expansions should be double quoted. In your command you use $f2
unquoted as a path name to a directory. This would fail if $f2
contains spaces.
Single quotes stops the shell from expanding a variable, which means that your sed
script is looking for lines matching the literal regular expression $f1
. This regular expression will never match as the $
will only match at the end of a line, and there will be no line that ends and then contains the characters f1
on the same line. Double quoting the sed
editing script will make the shell expand the $f1
variable before invoking sed
.
The pattern vcs*.pv
is supposed to be an argument to the -name
option of find
, but since it's unquoted it would expand to any name in the current directory that matches that globbing pattern. So if you had a file in the current directory whose name was vcs-test.pv
, find
would be invoked with -name vcs-test.pv
and you would only ever find files with that name. If you had several matching names in the current directory, you would cause find
to complain about unknown options.
The export.csv
file is outputted to (and emptied before any output from the loop happens). You would want the loop to read from it. This involves changing >
to <
.
The script, corrected:
while IFS=',' read f1 f2; do
find "$f2" -type f -name 'vcs*.pv' -exec sed -i "/$f1/d" {} +
done <export.csv
I have also added -type f
to the find
command line as we probably do not want to accidentally pick up directory names. I have also made it so that the IFS
variable is set only for the read
command.
This is a variation on the above in the case that all files are located directly below the top directory whose name you are reading from the CSV file:
while IFS=',' read dir pattern; do
for name in "$dir"/vcs*.pv; do
test -f "$name" && sed -i "s/$pattern/d" "$name"
done
done <export.csv
The good thing with this is that you get rid of find
. The bad thing is that you now have one invocation of sed
per file (usually not an issue unless you have hundreds or more files).
The following is a variation on the above that deletes lines depending on the string read from the CSV file. The difference is that the pieces of code above all interpret the pattern as a regular expression, not as a fixed string. This matters if your string contains characters that are interpreted a "special" in a regular expression, such as .
, *
, [
, ]
etc.
while IFS=',' read dir string; do
for name in "$dir"/vcs*.pv; do
[ ! -f "$name" ] && continue
grep -v -F -e "$string" "$name" >"$name.tmp" && mv -f "$name.tmp" "$name"
done
done <export.csv
done > export.csv
-->done < export.csv
– RomanPerekhrest Jan 20 '18 at 15:17ap01
from theexport.csv
file to the script for processing, then you didn't use the> export.csv
redirection. Post the script you actually used. – ilkkachu Jan 20 '18 at 19:16