6

Я использую это как str_replace для каждого файла в папке после разархивирования архива во временной папке

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

но я получаю эту ошибку:

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

Мой TMP Var:

tmp = mktemp -d

Что я делаю неправильно?

ОБНОВИТЬ

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)

1 ответ1

16

О, дорогой, ты жертва самой страшной вещи в мире: ты заглянул в интернет, чтобы найти фрагменты сценариев оболочки, ты нашел их много, но тебе никогда не говорили, что большинство из них полностью сломаны. Большинство из них ломаются, если сталкиваются с именами файлов с пробелами в них.

Обычно это относится ко всем сценариям, которые анализируют выходные данные команды, предназначенной для вывода информации, читаемой людьми, например, find или ls .

В вашем случае у вас есть файл /tmp/tmp.Q18p8BRYcc/steam engine.txt который содержит пробел и нарушает вашу команду.

Пожалуйста, рассмотрите возможность использования find правильно, с ключом -exec :

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

В этом случае find будет -exec часть

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

с заполнителем {} замененным найденными именами файлов ... но замененным должным образом, таким образом, он не может разбить, если имя файла содержит пробелы, переводы строки или другие забавные символы. Ну, это может сломаться, если {} окажется замененным чем-то, начинающимся с дефиса (но это маловероятно, если переменная $tmp расширится до такой вещи); в этом случае,

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

будет делать, если sed версия поддерживает опцию -- конечно.

Вы можете заменить трейлинг \; (это означает конец аргументов команды для выполнения) с помощью + так что sed будет запущен с таким количеством аргументов, которые он может обработать, поэтому он не будет порожден один раз для каждого файла.


Тем не менее, есть еще один способ безопасно использовать find с xargs , используя опцию -print0 find и опцию -0 xargs:

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .