sed: não é possível ler: nenhum arquivo ou diretório

6

Eu uso isso como str_replace para cada arquivo na pasta após descompactar o arquivo na pasta temporária

find "$tmp" -type f | xargs sed -i "s/${targetsubstring}/${newsubstring}/g"

mas recebo este erro:

sed: can't read /tmp/tmp.Q18p8BRYcc/steam: No such file or directory
sed: can't read engine.txt: No such file or directory

Meu tmp var:

tmp=mktemp -d

O que estou fazendo de errado?

UPDATE

archive='readlink -e $1' #First param is tar archive without file structure (only text files inside)
targetsubstring=$2 #Substring to replace
newsubstring=$3 #Substring to replaced by
tmp='mktemp -d' #Create a room to unzip our archive

if [ -f "$archive" ]; #Check if archive exist
then
    echo "Well done! (And yeah, I know about [ ! -f '$1' ], but where would be the fun?)" >/dev/null
else
    echo "File doesn't exist! Terminating program." >&2
    exit 1
fi
tar xvf "$archive" -C "$tmp" >/dev/null #Unzip archive to temp folder
find "$tmp" -type f | xargs sed -i "s/${targetsubstring}/${newsubstring}/g" #For every file do str_replace (There is a problem somwhere)
cd  "$tmp" 
tar -zcf "$archive" .  #Zip this to original file (I don't want any folder in my tar file)
    
por JohnDow 17.11.2013 / 15:07

1 resposta

15

Oh, querida, você é uma vítima da coisa mais terrível do mundo: você procurou na Internet para encontrar trechos de scripts de shell, você encontrou muitos deles, mas nunca lhe disseram que a maioria deles é completamente quebrado. A maioria deles quebra se encontrar nomes de arquivos com espaços neles.

Este é tipicamente o caso de todos os scripts que analisam a saída de um comando designado para produzir informações legíveis por seres humanos, por exemplo, find ou ls .

No seu caso, você tem o arquivo /tmp/tmp.Q18p8BRYcc/steam engine.txt que contém um espaço e que quebra seu comando.

Por favor, considere o uso de find corretamente , com sua opção -exec :

find "$tmp" -type f -exec sed -i "s/${targetsubstring}/${newsubstring}/g" {} \;

Nesse caso, find irá -exec ute a parte

sed -i "s/${targetsubstring}/${newsubstring}/g" {}

com o marcador de posição {} substituído pelos nomes de arquivos encontrados ... mas substituído corretamente de uma maneira que não possa ser encontrado se o nome do arquivo contiver espaços, novas linhas ou outros símbolos engraçados. Bem, ele pode quebrar se {} for substituído por algo que comece com um hífen (mas isso é improvável, a menos que a variável $tmp se expanda para tal coisa); neste caso,

sed -i "s/${targetsubstring}/${newsubstring}/g" -- {}

fará, se sua versão sed suportar a opção -- , é claro.

Você pode substituir o \; (que significa fim dos argumentos de comando a executar ) por + , de forma que sed seja lançado com tantos argumentos que ele possa manipular, então não será gerado uma vez por arquivo.

Ainda, há outra maneira de usar find com segurança com xargs , usando a opção -print0 de find e a opção -0 de xargs :

find "$tmp" -type f -print0 | xargs -0 sed -i "s/${targetsubstring}/${newsubstring}/g"
    
por 17.11.2013 / 16:28

Tags