Команда sed не работает должным образом при использовании подстановочного знака - PullRequest
0 голосов
/ 15 февраля 2020

Я пытаюсь использовать команду «sed», чтобы удалить последнюю строку файлов, которая соответствует шаблону с подстановочными знаками, заданным в качестве аргумента командной строки, и переместить файл из этого каталога в текущий каталог. Код выглядит следующим образом:

DIR="/home/usr_name/trash/"
for file in "$@"
    do
        if [ $file != "-h" ] //ignore this line
        then
            temp="$DIR$file"
            sed '$d' "$DIR$file"
            mv $temp .
        fi
    done

Код перемещает файл, но не выполняет команду sed для удаления последней строки. Давая подстановочный знак как ab *, он выдает следующую ошибку:

sed: can't read /home/usr_name/trash/ab*: No such file or directory

Помогите мне разобраться в этой ситуации.

Ответы [ 2 ]

0 голосов
/ 15 февраля 2020

Когда вы запускаете

yourcript ab*

, оболочка пытается развернуть подстановочный знак в текущем каталоге, а затем передает результат как "$@". Если в текущем каталоге нет совпадений, расширенный подстановочный знак (в традиционной конфигурации оболочки по умолчанию) теперь является литеральным строкой ab*, и дальнейшее расширение подстановочного знака не будет предприниматься. .

(Bash имеет nullglob для изменения этого поведения, так что подстановочный знак, который не соответствует ни одному файлу, заменяется ничем; но это на самом деле не помогает.)

Если подстановочный знак соответствует , совпадает с некоторыми файлами, есть вероятность, что эти файлы не будут существовать в другом каталоге, или (в общем случае), что файлы с этими именами не будут файлами, которые вы на самом деле хотел обработать.

В худшем случае, может быть есть некоторые файлы в текущем каталоге, которые соответствуют шаблону и , они все дублируют файлы с одинаковым именем в каталог назначения. Так что если у вас есть ab и abc как в текущем каталоге, так и в другом каталоге, но другой каталог также содержит abecedary и abugida, ваша команда обработает только первые два, и вы не получите предупреждение о том, что два других никогда не были сопоставлены и обработаны.

Итог, возможно, переосмыслите свой подход, чтобы передать полный путь к файлам, которые вы хотите обработать в сценарии; тогда все остальное легко, и поведение вашего скрипта будет предсказуемым и совместимым с поведением других утилит обработки файлов.

Вам все равно нужно будет sed фактически изменять каждый файл. Просто sed '$d' files не изменит files, просто выведите измененное содержимое на стандартный вывод. Если у вас есть sed -i, возможно, используйте это.

for file in "$@"
do
    # Note added quotes
    if [ "$file" != "-h" ] # ignore this line
    then
        sed -i '$d' "$file"
        mv "$file" .
    fi
done

Использование:

yourscript /home/usr_name/trash/ab*
0 голосов
/ 15 февраля 2020

Если вам нужны символы подстановки, самое простое решение будет использовать find:

find "$DIR" -name "$file" \
   -exec sed -i '$d' {} \; 
   -exec mv {} "$DEST" \;
  • -name "$file" - это скажет find для поиска файлов, соответствующих символу подстановки
  • -exec sed -i '$d' {} \; - выполнить sed для каждого найденного файла {} представляет файл
  • -exec mv {} "$DEST" \; - переместить файл

отметить, что порядок execs mater после перемещения файл не будет доступен в старом месте.

Редактировать: Первоначально я предполагал, что 'ab*' был задан в качестве параметра в кавычках для всего сценария. Этот ответ напомнил мне еще одну возможность: вы запускаете скрипт из каталога, в котором нет файлов, начинающихся с «ab», в этом случае «ab *» не раскрывается, и mv будет работать в вашем сценарии, но не в sed (поскольку вы цитируете «файл $ DIR $», посмотрите выходные данные отладки bash:

sorin@testvm ~/tmp $ seq 1 2 > src/ab1
sorin@testvm ~/tmp $ seq 1 4 > src/ab5
sorin@testvm ~/tmp $ seq 1 3 > src/ab3
sorin@testvm ~/tmp $ bash -x test.sh ab*
+ DIR=src/
+ for file in '"$@"'
+ '[' 'ab*' '!=' -h ']'
+ temp='src/ab*'
+ sed '$d' 'src/ab*'
sed: can't read src/ab*: No such file or directory
+ mv src/ab1 src/ab3 src/ab5 .
sorin@testvm ~/tmp $

Это в точности соответствует сценарию, описанному в вашем вопросе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...