Existem alguns problemas com o código e o arquivo de entrada nesta pergunta:
-
O arquivo de entrada obviamente tem retornos de carro à direita ( \r ) em cada linha. Provavelmente, isso deve ter sido criado em uma máquina Windows como um arquivo de texto do DOS. A maneira usual de se livrar desses retornos de carro é executar dos2unix no arquivo. Veja, por exemplo, a pergunta What é '^ M' e como posso me livrar disso?
-
Todas as expansões variáveis devem ser duplamente citadas. Em seu comando, você usa $f2 sem aspas como um nome de caminho para um diretório. Isso falharia se $f2 contivesse espaços.
-
As aspas simples impedem que o shell expanda uma variável, o que significa que o script sed está procurando por linhas que correspondam à expressão regular literal $f1 . Essa expressão regular nunca corresponderá, pois o $ corresponderá apenas ao final de uma linha e não haverá linha que termine e, em seguida, contenha os caracteres f1 na mesma linha . Duplicar o script de edição sed fará com que o shell expanda a variável $f1 antes de invocar sed .
-
O padrão vcs*.pv deve ser um argumento para a opção -name de find , mas como não é citada, ele se expande para qualquer nome no diretório atual que corresponda a esse padrão de globbing. Portanto, se você tivesse um arquivo no diretório atual cujo nome fosse vcs-test.pv , find seria invocado com -name vcs-test.pv e você só encontraria arquivos com esse nome. Se você tivesse vários nomes correspondentes no diretório atual, você faria com que find reclamasse sobre opções desconhecidas.
-
O arquivo export.csv é enviado para (e esvaziado antes que qualquer saída do loop aconteça). Você gostaria que o loop fosse lido a partir dele. Isso envolve alterar > para < .
O script corrigido:
while IFS=',' read f1 f2; do
find "$f2" -type f -name 'vcs*.pv' -exec sed -i "/$f1/d" {} +
done <export.csv
Também adicionei -type f à linha de comando find , pois provavelmente não queremos que os nomes de diretório sejam pegos acidentalmente. Eu também fiz isso para que a variável IFS seja definida somente para o comando read .
Esta é uma variação do acima, no caso de todos os arquivos estarem diretamente abaixo do diretório principal cujo nome você está lendo no arquivo CSV:
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
O bom disso é que você se livra de find . O ruim é que agora você tem uma invocação de sed por arquivo (geralmente não é um problema, a menos que você tenha centenas ou mais arquivos).
A seguir, uma variação acima, que exclui linhas dependendo da string lida no arquivo CSV. A diferença é que os trechos de código, acima de tudo, interpretam o padrão como uma expressão regular , não como uma string fixa. Isso é importante se a string contiver caracteres interpretados como "especiais" em uma expressão regular, como . , * , [ , ] 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