rm не удается удалить файлы с помощью подстановочного знака из сценария, но работает из командной строки
я столкнулся с очень глупой проблемой с сценарием оболочки Linux. Я хочу удалить все файлы с расширением". bz2 " в директории. В скрипте я называю
rm "$archivedir/*.bz2"
где $archivedir-это путь к каталогу. Должно быть довольно просто, не так ли? Каким-то образом ему удается потерпеть неудачу с этой ошибкой:
rm: cannot remove `/var/archives/monthly/April/*.bz2': No such file or directory
а там и файл в этом каталоге называется test. bz2 и если я изменю свой скрипт на
echo rm "$archivedir/*.bz2"
и скопируйте / вставьте вывод эта строка в окне терминала файл удаляется успешно. Что я делаю не так?
6 ответов:
TL; DR
цитируйте только переменную, а не весь ожидаемый путь с подстановочным знаком
rm "$archivedir"/*.bz2
объяснение
в Unix программы обычно сами не интерпретируют подстановочные знаки. Оболочка интерпретирует некотируемые подстановочные знаки и заменяет каждый аргумент подстановочного знака списком соответствующих имен файлов. если $archivedir может содержать пробелы, то
rm $archivedir/*.bz2
может не делать то, что вывы можете отключить этот процесс процитировать символ подстановки, используя двойные или одинарные кавычки или обратную косую черту перед ним. Однако это не то, что вы хотите здесь - вы хотите, чтобы подстановочный знак был расширен до списка файлов, которым он соответствует.
будьте осторожны с написанием
rm $archivedir/*.bz2
(без кавычек). Разбиение слова (т. е. разбиение командной строки на аргументы) происходит после $archivedir заменен. Так что если $archivedir содержит пробелы, тогда вы получите дополнительные аргументы, которые вы не намерены. Сказать archivedir составляет/var/archives/monthly/April to June
. Тогда вы получите эквивалент написанияrm /var/archives/monthly/April to June/*.bz2
, который пытается удалить файлы "/var / archives/monthly/April", "to" и все файлы, соответствующие "June/*. bz2", что не то, что вы хотите.правильное решение-написать:
rm "$archivedir"/*.bz2
Ваша исходная строка
rm "$archivedir/*.bz2"
можно переписать как
rm "$archivedir"/*.bz2
для достижения того же эффекта. Расширение подстановочных знаков не выполняется должным образом в существующей настройке. Перемещая двойную кавычку в "переднюю" часть пути к файлу (что является законным), вы избегаете этого.
просто чтобы немного расширить это, bash имеет довольно сложные правила для работы с метасимволами в кавычках. В общем
почти ничего не интерпретируется в одиночные кавычки:
echo '$foo/*.c' => $foo/*.c echo '\*' => \*
подстановка оболочки выполняется внутри двойных кавычек, но метасимволы файлов не расширяются:
FOO=hello; echo "$foo/*.c" => hello/*.c
все, что находится внутри обратных кавычек, передается в подоболочку, которая их интерпретирует. Переменная оболочки, которая не экспортированный не определяется в подобласти. Итак, первая команда отдается пустым эхом, а вторая и третья эхом "пока":
BAR=bye echo `echo $BAR` BAR=bye; echo `echo $BAR` export BAR=bye; echo `echo $BAR`
(и получить это, чтобы напечатать так, как вы хотите его в SO
нескольких попытокэто, видимо, невозможно...)