Как использовать пробелы в функции «for» [дубликат]

На этот вопрос уже есть ответ здесь:

Проблема в том, что я делаю скрипт для класса, и вопрос в том, «Сделать скрипт который называет все файлы в фактическом каталоге и сообщает нам имя и разрешения, которые у них есть ", поэтому я сделал следующий сценарий:

#!/bin/bash

for name in `ls -l . | awk {print'$9'}`
do
echo "The file $name has the following permissions: `ls -l . | grep $name | cut -d" " -f1`"
done

Хорошо, сценарий работает отчасти, но проблема в том, что он не отображает все файлы в списке ls -l , потому что я печатаю 9-й столбец (имя файла), но если в нем есть пробел, слово после пробела находится в ] column 10 , поэтому я попробовал вот так:

#!/bin/bash

for name in `ls -l . | awk {print'$9,$10'}`
do
echo "The file $name has the following permissions: `ls -l . | grep $name | cut -d" " -f1`"
done

Но когда я это сделаю, проблема в том, что переменная $ name будет ссылаться на первый столбец и второй столбец как на отдельные слова, и она покажет оба как будто это разные файлы.

Я также попытался экранировать пробелы в ls с помощью ls -lb , но тогда команда grep не сработала, и если я использую grep '$ name \ s' он скопирует буквально $ name \ s, поэтому ничего не будет искать в команде ls ...

Может быть, эту проблему действительно легко решить , но я занимался этим более 5 часов и ничего ... Любая помощь приветствуется!

4
задан 7 March 2018 в 01:22

2 ответа

Не анализировать ls! Вместо этого используйте шарик:

for name in ./*; do

Существуют другие способы, которыми можно улучшить сценарий также.

  1. В цикле снова не анализируйте ls. Вместо этого используйте stat получить полномочия непосредственно 1
  2. Используйте более новый синтаксис замены команды $(...) вместо обратных галочек устаревших `...`
  3. Определите переменную $perms заставить печать представить в виде строки немного более чистый и легче читать.

Так:

for name in ./*; do
    perms="$(stat -c "%A" "$name")"
    echo "The file $name has the following permissions: $perms"
done

Сноски:

  1. Если stat не существовал, и необходимо было получить полномочия от ls, Вы дали бы ему имя файла как аргумент и использовали бы -d отметьте, таким образом, это не убывает в каталоги или разыменовывает символьные ссылки.

    ls -ld "$name" | cut -d" " -f1
    

    Но снова, Вы не должны анализировать ls. Этот метод перестал работать, если какие-либо из имен файлов содержат новые строки.

8
ответ дан 23 November 2019 в 11:36

Это - определенно не хороший план записать вещи как

for stuff in `ls`; ...

Парсинг вывода ls действительно плохая идея потому что вывод ls просто текст и ненадежное представление подлинных имен Ваших файлов.

Чтобы сделать вещи с файлами используют шарики оболочки вместо этого.

for stuff in *; ...

Вместо *, можно использовать ./* что означает то же самое, но более безопасен, потому что все пути запускаются с ./ (текущий каталог) вместо любого подозрительного символа, с которого запускаются Ваши имена файлов, который мог быть тем, который заставляет оболочку выполнять расширение (такой как ~) (хотя необходимо определенно "заключить переменные в кавычки" для предотвращения таких нежелательных расширений оболочки), или тот, который команда, которую Вы пытаетесь использовать, может попытаться интерпретировать особенно (такой как -). Можно также использовать * и нет ./*, но добавьте -- после всех опций к командам Вы работаете в цикле, для предотвращения начала имен файлов - быть интерпретируемым как опции. Это дает чистый путь, но если Вы хотите использовать ./* можно иногда чистить использование пути "$(basename $var)" в командах или других приемах. Знайте что не вся поддержка команд -- указать на конец опций.

Вместо того, чтобы пытаться проанализировать то, из чего Вы хотите ls -l, используйте команду специально для отображающихся метаданных файла и попросите только вывод, который Вы хотите.

stat -c "%n %A" file

должен дать Вам, что Вы хотите. Если Вы хотите отобразить сообщение, можно просто записать это в :)

Вот то, как я сделал бы это:

for file in *; do stat -c 'The permissions of %n are: %A' -- "$file"; done
8
ответ дан 23 November 2019 в 11:36

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

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