Использование mv для перехода в другой каталог и одновременного переименования

Это не чтение, а эхо.

Я написал script.sh и вызвал его, используя sh script.sh.

В Debian и Ubuntu sh — это тире, в котором echo оценивает обратную косую черту в стиле C в своих аргументах:

$ dash -c 'foo="foo\000bar"; echo "$foo"; printf "%s\n" "$foo"' 
foo
foo\000bar

]\000 превращается в байт NUL, который, по-видимому, завершает строку, которую выводит echo. Заключение переменной в кавычки здесь не помогает, так как это только изменяет обработку командной строки оболочки перед запуском самой команды, а здесь сам echo обрабатывает обратную косую черту.

Это известная проблема переносимости, более подробно описанная здесь: Почему printf лучше, чем echo?

Например, echo в Bash выполняет обратную косую черту, если задан аргумент -e.

Первоначально вопрос был помечен как , поэтому, если вы хотите запустить скрипт с помощью Bash, запустите его с помощью bash script.sh, а не sh script.sh. .

1
23.05.2017, 15:40
2 ответа

Я немного улучшил решение lark, чтобы сделать только один вызов sh :

find / -size +100M -atime +30 -exec sh -c \
  'for f do mv "$f" /tmp/big-not-used/"$(basename "$f")$(date +%Y-%m-%d)"; done' sh {} +

В качестве альтернативы, вообще без каких-либо вызовов sh :

while IFS= read -r f; do
  mv "$f" /tmp/big-not-used/"$(basename "$f")$(date +%Y-%m-%d)"
done < <(find / -size +100M -atime +30)

(Последнее при предположении, что в именах файлов нет символов новой строки.)

Для отладки вы можете добавить -v в mv (если это поддерживается).

0
28.01.2020, 01:08

Вы приближались с:

find / -size +100M -atime +30 \
  -exec mv {} /big-not-used/$(basename {})$(date +%Y-%m-%d) \;

Но без цитирования, расширение оболочки $ (...) конструкции происходят до того, как команда find выполнит . Другими словами, учитывая приведенную выше командную строку, которая фактически выполняется:

find / -size +100M -atime +30 \
  -exec mv {} /big-not-used/{}2016-10-30 \;

Потому что результатом $ (basename {}) является просто {} , и поэтому вы закончить с полным именем пути. Попробуйте вместо этого:

find / -size +100M -atime +30 \
  -exec sh -c 'mv {} /tmp/big-not-used/$(basename {})$(date +%Y-%m-%d)' \;

Для проверки вы можете заменить mv на echo mv , например:

find / -size +100M -atime +30 \
  -exec sh -c 'echo mv {} /tmp/big-not-used/$(basename {})$(date +%Y-%m-%d)' \;

... и посмотреть, как выглядят сгенерированные команды.

0
28.01.2020, 01:08

Теги

Похожие вопросы