Как сохранить имя файла с косой чертой

Обновлено: 03.07.2024


Я пишу сценарий для резервного копирования. Я составляю список файлов следующим образом:

Переменная LISTOFFILES хранит примерно что-то вроде:

Мой следующий шаг:

Я понимаю, что Баш предполагает, что Python и Tutorial.pdf это разные файлы.

Есть ли способ сделать список файлов с обратной косой чертой, включенный в find или я должен использовать ls с трубами?

Я хочу прочитать ваши советы и рекомендации.

Другой мой вопрос:

Ответ на этот вопрос не очень важен, но один совет может помочь

Как вывести список файлов только с именем файла без пути к файлу?

Например: file вместо /home/user/file .

Я пытаюсь с find команда с prune и path варианты, но мне это не удалось.

Что касается вашего основного вопроса, вам нужно будет использовать другой подход. Ваш метод помещает все файлы в одну строку в $ LISTOFFILES. Затем, когда вы переходите к нему, вы не используете кавычки, которые заставляют его разбиваться на пробелы и давать вам результат, который вы видите.

Самый простой способ получить желаемый результат:

Что мы сделали, так это запустить find и разделить каждый результат символом NULL (часть -print0). Результат find затем передается по конвейеру в xargs, который читает список файлов, разделенных символом NULL (аргумент -0 указывает xargs сделать это), и передает этот список файлов в качестве аргументов в tar.

По вашему второму вопросу: если вы хотите получить только имена файлов только из find команда, используйте printf

Если вы имеете в виду в целом, а не только с помощью find, проще всего использовать basename .

basename предназначено именно для этого и ничего больше.

  • 1 . или, если вы не хотите создавать новый процесс с basename вы можете использовать расширение параметра.
  • Да, собирался сделать простое более эффективным :-). Есть также проблемы с этой первой командой, например, когда вы получаете большое количество файлов, поскольку вы можете превысить максимальное количество аргументов (в дополнение к созданию дополнительной процедуры для xargs). Можно сделать цикл чтения во время, но гораздо сложнее.

Вы можете собрать список имен файлов, возвращаемых find , но только если в именах файлов нет новых строк, и вам нужно принять меры предосторожности.

Когда вы пишете замену команды или расширение переменной без кавычек, например $LISTOFFILES здесь оболочка выполняет разделение слов и подстановку (подстановочные знаки) в результате.

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

Здесь вам нужно опустить двойные кавычки, потому что разделение слов - это то, что разбивает строку на биты, разделенные новой строкой. Но по умолчанию он также разделяется на другие символы пробела. Так что вам нужно сделать это безопасным, а также отключить глобус. Вы достигнете первого, установив IFS переменную в одну новую строку, а последнюю - путем вызова set -f .

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

Обычный способ использования find

Вместо того, чтобы анализировать вывод find , вы должны заставить его вызывать команду, которую вы хотите запустить для файлов, через -exec действие.Это позаботится о случае, когда файлов так много, что превышена максимальная длина командной строки: программа запускается столько раз, сколько необходимо.

Здесь это немного сложно, потому что вы не можете вызывать tar -c несколько раз (при каждом вызове он будет начинаться с нового пустого архива). Но см. Tar up все PDF-файлы в каталоге, сохранив структуру каталогов

Более простые методы

Если файлов не так много, и вы используете ksh93 или bash ≥4 или zsh, используйте ** подстановочный знак для рекурсии в подкаталоги. Сначала вам нужно установить некоторые параметры оболочки:

В zsh без особых настроек вы можете записать этот шаблон как

/**/*.(PDF|pdf|ODT|odt) . После setopt extglob , вы можете написать это как

Или вы можете использовать pax:

Если вам не нужен префикс пути

Есть способы с tar и pax , но самый простой способ - сначала перейти в каталог, который вы хотите заархивировать.

Первый вопрос:

Ответ на ваш первый вопрос: quotes .

Вместо того, чтобы делать -> tar cvf backup.tar $LISTOFFILES

Сделай это -> tar cvf backup.tar '$LISTOFFILES'

Давайте посмотрим на пример (я взял один из ваших файлов для этой демонстрации, даже если файл не существует на моем компьютере, посмотрите на ошибку, которую я получаю с кавычками и без них) -

Ошибка появилась для двух файлов /home/user/Python и Tutorial.pdf . Поставим quote нашим variable и посмотрим, что у нас получится.

Ошибка появилась только один раз для файла /home/user/Python Tutorial.pdf

Второй вопрос:

Подрезать /path/to/file есть несколько способов. Моим любимым было бы awk но я покажу тебе одну для sed тоже.

sed метод:

Вы можете включить это в свой скрипт следующим образом:

Здесь нужно помнить, что мы делаем substitution . Мы заменяем /home/user/ к nothing . Если ты find файлы из более чем одного каталога, то вы можете сделать тонны и тонны замен (yikes!) или сделать awk путь.

awk метод:

Ага, вот и все. Будет работать для файлов, которые вы find в любом каталоге или их подкаталогах.

Итак, ваш сценарий может иметь это следующим образом -

Другие советы и хитрости:

Вот несколько случайных советов, которые, я думаю, могут быть вам полезны -

Чтобы find имена файлов insensitively , используйте iname вместо того, что у вас есть прямо сейчас. Проверь это -

Другие способы обрезки /path/to/file с помощью basename . Я приведу пример, и вы можете включить его в свой сценарий, если вам будет удобно.

Надеюсь это поможет!

  • Ваше решение для цитаты не сработает, потому что все файлы будут объединены как один аргумент. Единственный способ сделать это с переменными оболочки - использовать массив, который не может работать (надежно) с первоначально используемым подходом.
  • Я попробовал на своем компьютере. Работал нормально. [jaypal:

Читайте также: