Создание сценария Bash 'для' имен файлов дескриптора с пробелами (или обходное решение)

Пока я использовал Bash в течение нескольких лет, мой опыт со сценариями Bash относительно ограничен.

Мой код как ниже. Это должно захватить всю структуру каталогов из текущего каталога и копировать его в $OUTDIR.

for DIR in `find . -type d -printf "\"%P\"\040"`
do
  echo mkdir -p \"${OUTPATH}${DIR}\"        # Using echo for debug; working script will simply execute mkdir
  echo Created $DIR
done

Проблема, вот образец моей файловой структуры:

$ ls
Expect The Impossible-Stellar Kart
Five Iron Frenzy - Cheeses...
Five Score and Seven Years Ago-Relient K
Hello-After Edmund
I Will Go-Starfield
Learning to Breathe-Switchfoot
MMHMM-Relient K

Отметьте пробелы :-S И for берет параметры пословно, таким образом, вывод моего сценария выглядит примерно так:

Creating directory structure...
mkdir -p "/myfiles/multimedia/samjmusicmp3test/Learning"
Created Learning
mkdir -p "/myfiles/multimedia/samjmusicmp3test/to"
Created to
mkdir -p "/myfiles/multimedia/samjmusicmp3test/Breathe-Switchfoot"
Created Breathe-Switchfoot

Но мне нужен он для захвата целых имен файлов (одна строка за один раз) от вывода find. Я также попытался делать find поместите двойные кавычки вокруг каждого имени файла. Но это не помогает.

for DIR in `find . -type d -printf "\"%P\"\040"`

И произведенный с этой измененной строкой:

Creating directory structure...
mkdir -p "/myfiles/multimedia/samjmusicmp3test/"""
Created ""
mkdir -p "/myfiles/multimedia/samjmusicmp3test/"Learning"
Created "Learning
mkdir -p "/myfiles/multimedia/samjmusicmp3test/to"
Created to
mkdir -p "/myfiles/multimedia/samjmusicmp3test/Breathe-Switchfoot""
Created Breathe-Switchfoot"

Теперь, мне нужен некоторый способ, которым я могу выполнить итерации через подобный этого, потому что я также хочу выполнить более сложное вовлечение команды gstreamer на каждом файле в следующей подобной структуре. Как я должен делать это?

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

Решение: Я первоначально попробовал:

find . -type d | while read DIR
do
  mkdir -p "${OUTPATH}${DIR}"
  echo Created $DIR
done

Это хорошо работало по большей части. Однако я позже нашел, что начиная с результатов канала в цикле с условием продолжения, работающем в подоболочке, любой набор переменных в цикле был позже недоступный, который сделал реализацию ошибочного счетчика довольно трудной. Мое конечное решение (из этого ответа на ТАК):

while read DIR
do
  mkdir -p "${OUTPATH}${DIR}"
  echo Created $DIR
done < <(find . -type d)

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

12
задан 23.05.2017, 15:41

7 ответов

Необходимо передать по каналу find в a while цикл.

find ... | while read -r dir
do
    something with "$dir"
done

Кроме того, Вы не должны будете использовать -printf в этом случае.

Можно сделать это доказательство против файлов с новыми строками на их имена, при необходимости при помощи nullbyte разделителя (что быть единственным символом, который не может появиться в *, отклоняет filepath):

find ... -print0 | while read -d '' -r dir
do
    something with "$dir"
done

Вы также найдете использование $() вместо обратных галочек, чтобы быть более универсальным и легче. Они могут быть вложены намного более легко, и заключение в кавычки может быть сделано намного более легко. Этот изобретенный пример проиллюстрирует эти тезисы:

echo "$(echo "$(echo "hello")")"

Попытайтесь сделать это с обратными галочками.

11
ответ дан 07.12.2019, 11:47

См. этот ответ, который я записал несколько дней назад для примера сценария, который обрабатывает имена файлов с пробелами.

Существует немного более замысловатое (но более кратко) способ достигнуть того, что Вы пытаетесь сделать хотя:

find . -type d -print0 | xargs -0 -I {} mkdir -p ../theredir/{}

-print0 говорит находят для разделения споров с пустым указателем;-0 к xargs говорят этому ожидать аргументы, разделенные пустыми указателями. Это означает, что обрабатывает прекрасные пробелы.

-I {} говорит xargs заменять строку {} с именем файла. Это также подразумевает, что только одно имя файла должно использоваться на командную строку (xargs, будет обычно наполнять столько, сколько будет соответствовать на строке),

Остальные должны быть очевидными.

8
ответ дан 07.12.2019, 11:47

Проблема, с которой Вы встречаетесь, для оператора, отвечает на находку как на отдельные аргументы. Разделитель пространства. Необходимо использовать переменную IFS удара для не разделения на пространстве.

Вот ссылка, которая объясняет, как сделать это.

Внутренняя переменная IFS

Один путь вокруг этой проблемы состоит в том, чтобы изменить внутреннюю IFS Bash (Внутренний Разделитель полей) переменная так, чтобы это разделило поля чем-то другим, чем пробел по умолчанию (пространство, вкладка, новая строка), в этом случае, запятая.

#!/bin/bash
IFS=$';'

for I in `find -type d -printf \"%P\"\;`
do
   echo "== $I =="
done

Установите свою находку, чтобы произвести Ваш разделитель полей после %P и установить Вашу IFS соответственно. Я выбрал точку с запятой, так как это очень маловероятно к найденному в Ваших именах файлов.

Другая альтернатива должна назвать mkdir от находки непосредственно через -exec можно ли пропустить для цикла в целом. Это - то, если Вы не должны делать никакого дополнительного парсинга.

5
ответ дан 07.12.2019, 11:47

Если тело Вашего цикла является больше, чем единственная команда, возможно использовать xargs для управления сценарием оболочки:

export OUTPATH=/some/where/else/
find . -type d -print0 | xargs -0 bash -c 'for DIR in "$@"; do
  printf "mkdir -p %q\\n" "${OUTPATH}${DIR}"        # Using echo for debug; working script will simply execute mkdir
  echo Created $DIR
done' -

Обязательно включайте запаздывающего тире (или некоторое другое 'слово'), если оболочка имеет разнообразие Границы/POSIX (это используется для установки 0$ в сценарии оболочки). Кроме того, заботу нужно соблюдать о заключении в кавычки, так как сценарий оболочки пишется в заключенной в кавычки строке вместо непосредственно при подсказке.

4
ответ дан 07.12.2019, 11:47

в Вашем обновленном вопросе Вы имеете

mkdir -p \"${OUTPATH}${DIR}\"

это должно быть

mkdir -p "${OUTPATH}${DIR}"
1
ответ дан 07.12.2019, 11:47

или сделать все это намного менее сложным:

% rsync -av --include='*/' --exclude='*' SRC DST

это копирует структуру каталогов SRC в DST.

0
ответ дан 07.12.2019, 11:47

Если у Вас есть Параллель GNU http://, www.gnu.org/software/parallel/ установил Вас, может сделать это:

find . -type d | parallel echo making {} ";" mkdir -p /tmp/outdir/{} ";" echo made {}

Посмотрите вводное видео для Параллели GNU для узнавания больше: http://www.youtube.com/watch?v=OpaiGYxkSuQ

0
ответ дан 07.12.2019, 11:47

Теги

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