Заключает именам файлов в кавычки достаточно безопасности для выполнения 'xargs sudo комната-rf'?

Я записал сценарий, который удаляет все кроме последних двух файлов в папке:

#!/bin/bash
ls -1 --quoting-style=shell-always /path/to/some/folder \
    | head -n -2 \
    | xargs printf -- "'/path/to/some/folder/%s'\n" \
    | xargs sudo rm -rf

Этот сценарий будет выполняться как задание крона каждый день.

Обоснование следующие:

  1. Получите список всего использования файлов ls -1 (так, чтобы я получил один файл на строку);

  2. Удалите последние два из использования списка head -n -2;

  3. С тех пор ls относительные пути печати, используйте xargs printf вещь предварительно ожидать путь к папке и сделать это полным путем;

  4. Отправьте их в sudo rm -rf использование xargs.

У всех есть доступ к этой папке, таким образом, любой может создать и удалить любые файлы в этой папке.

Проблема: sudo rm -rf страшно. xargs sudo rm -rf невероятно страшно.

Я хочу быть уверенным, что никто не может повредить другие папки/системы путем создания умных файлов, которые будут удалены (или случайно или нарочно). Я не знаю, что-то умное как:

file with / spaces.txt

который мог привести к супер страшному sudo rm -rf /.

Править: Моя ошибка, имена файлов не могут содержать /, таким образом, этой определенной проблемы не произошло бы, но вопрос о том, существуют ли другие риски, все еще стоит.

Поэтому я использую --quoting-style=shell-always, это должно предотвратить любые приемы с файлами с пробелами. Но теперь я задаюсь вопросом, мог ли кто-то быть дополнителен умный с пробелами и кавычками в имени файла, возможно.

Действительно ли мой сценарий безопасен?


Примечание: Мне нужно sudo потому что я получаю доступ к папке удаленно (от использования подключенного сетевого диска mount), и я не мог заставить это работать без sudo.

10
задан 5 September 2018 в 15:31

2 ответа

В Linux любой символ является допустимым символом образования имени файла кроме:

  • \0 (ASCII NUL): как используется для строкового завершения в C
  • / (наклонная черта вправо): как используется для разделения пути

Так, Ваш подход не будет определенно работать во многих случаях, как Вы можете предположить, например, делаете он обрабатывает новую строку (\n) в имени файла? (Подсказка: Нет).

Немного примечаний:

  • Не анализировать ls; используйте специальные инструменты (существует по крайней мере один для большинства вариантов использования),
  • При контакте с именами файлов попытайтесь усилить разделенный вывод NUL, обеспеченный почти всеми инструментами GNU, которые работают с такими данными
  • Заботьтесь при передаче по каналу, удостоверьтесь, что обе программы могут понять разделения NUL
  • Каждый раз, когда Вы вызываете xargs, посмотрите, можно ли сойти с рук find ... -exec; в большинстве случаев Вы согласитесь только с find один

Я думаю, что они получат Вас идущий на данный момент. steeldriver уже обеспечил, NUL разделил идею в комментарии (printf -- '%s\0' /path/to/some/folder/* | head -zn -2 | xargs -0 rm), используйте это в качестве начальной точки.

10
ответ дан 23 November 2019 в 04:29

xargs действительно поддерживает некоторое заключение в кавычки: с одинарными кавычками, двойные кавычки или обратная косая черта, которая позволяет этому принимать произвольные аргументы ¹, но с синтаксисом, который отличается от синтаксиса заключения в кавычки подобных Границе оболочек.

Реализация GNU ls как найдено на Ubuntu не имеет никакого режима заключения в кавычки, который совместим с xargs формат ввода.

ls --quoting-style=shell-always совместимо с ksh93, ударом и оболочками zsh, заключающими синтаксис в кавычки, но только когда вывод ls интерпретируется оболочкой в той же локали как ls был, когда это произвело его. Кроме того, нужно избежать некоторых локалей, как те, которые используют BIG5, BIG5-HKSCS, GBK или GB18030.

Таким образом с теми оболочками, можно на самом деле сделать:

typeset -a files
eval "files=($(ls --quoting-style=shell-always))"
xargs -r0a <(printf '%s\0' "${files[@]:0:3}") ...

Но это имеет преимущество:

files=(*(N))                 # zsh
files=(~(N)*)                # ksh93
shopt -s nullglob; files=(*) # bash

Единственный случай, где это становится полезным, - когда Вы хотите использовать -t опция ls отсортировать файлы по mtime/atime/ctime или -S/-V. Но даже затем, Вы могли бы также использовать zsh:

files=(*(Nom))

например, отсортировать файлы по mtime (использование oL для -S, и n для -V).

Удалить всех кроме двух последний раз изменило регулярные файлы:

rm -f -- *(D.om[3,-1])

¹ существуют все еще некоторые ограничения длины ( execve() и в некотором не-GNU xargs реализации намного ниже произвольные), и некоторый не-GNU xargs реализации будут дросселировать входа, который содержит последовательности байтов, не формирующих допустимые символы.

3
ответ дан 23 November 2019 в 04:29

Другие вопросы по тегам:

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