На этот вопрос уже есть ответ здесь:
Проблема в том, что я делаю скрипт для класса, и вопрос в том, «Сделать скрипт который называет все файлы в фактическом каталоге и сообщает нам имя и разрешения, которые у них есть ", поэтому я сделал следующий сценарий:
#!/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 часов и ничего ... Любая помощь приветствуется!
Не анализировать ls
! Вместо этого используйте шарик:
for name in ./*; do
Существуют другие способы, которыми можно улучшить сценарий также.
ls
. Вместо этого используйте stat
получить полномочия непосредственно 1$(...)
вместо обратных галочек устаревших `...`
$perms
заставить печать представить в виде строки немного более чистый и легче читать.Так:
for name in ./*; do
perms="$(stat -c "%A" "$name")"
echo "The file $name has the following permissions: $perms"
done
Сноски:
Если stat
не существовал, и необходимо было получить полномочия от ls
, Вы дали бы ему имя файла как аргумент и использовали бы -d
отметьте, таким образом, это не убывает в каталоги или разыменовывает символьные ссылки.
ls -ld "$name" | cut -d" " -f1
Но снова, Вы не должны анализировать ls
. Этот метод перестал работать, если какие-либо из имен файлов содержат новые строки.
Это - определенно не хороший план записать вещи как
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