Я получаю разные ошибки при запуске кода ниже (он подсчитывает количество файлов .mp3 в каждом пользовательском каталоге):
for us in /home/*
do
if [ -d $us ]
then
LT=$(find $us -name "*.jpg" -o -name "*.mp4" -o -name "*.mp3")
N_MP3=$("$LT" | grep "\.mp3$" | wc -l)
N_MP3=$($LT | grep "\.mp3$" | wc -l)
N_MP3=$(find $us -name "*.jpg" -o -name "*.mp4" -o -name "*.mp3" | grep "\.mp3$" | wc -l)
fi
done
Учтите, что у нас есть в каком-то пользовательском каталоге, скажем, user=ubuntu, файлы:
Итак, запустим код:
(1) Выполнение "$LT" | ..., я получаю сообщение:
/home/ubuntu/Desktop/Songs/sample.mp3 /home/ubuntu/Desktop/Images/sample.jpg: Нет такого файла или каталога
что означает, что команда «$LT» была выполнена и обнаружила все файлы .mp4, .mp3 или .jpg в моем пользователе, а затем выдает эту ошибку.
(2) Выполнение $LT | ..., что эквивалентно $(find $us -name ".jpg" -o -name ".mp4" -o -name "*.mp3") | ... Я получаю сообщение /home/ubuntu/Desktop/Songs/sample.mp3: Отказано в доступе. Это означает, что команда $LT была выполнена и нашла только файл .mp3, а затем выдает эту ошибку.
Если я удалю sample.jpg из моего user=ubuntu, то в обоих случаях я получу одно и то же сообщение об ошибке: /home/ubuntu/Desktop/Songs/sample.mp3: Отказано в доступе.
Я знаю (но не знаю почему) я должен использовать команду echo перед $LT, но я хотел бы знать, что происходит в тех случаях, когда я раньше не использовал команду echo. Пожалуйста, может кто-нибудь пролить свет на эти ошибки?
Это происходит из-за разделения слов.
При разделении слов первое слово становится именем команды, а остальные слова становятся аргументами.
Если вы не разделяете слова, в качестве имени команды будет использоваться все значение.
Bash показывает имя команды, которую вы пытались выполнить, когда оно не найдено, поэтому значения отражаются в сообщении об ошибке:
$ var = "foo bar baz"
$ foo bar baz
-bash: foo: command not found
$ $var
-bash: foo: command not found
$ "foo bar baz"
-bash: foo bar baz: command not found
$ "$var"
-bash: foo bar baz: command not found
LT=$( ...)
Вы используете подстановку команд, поэтому вы не сохраняете строку для последующего повторного использования, вы пытаетесь выполнить вывод команды find; это не сработает.
Чуть более элегантно:
function lt() { find $1 -name "*.jpg" -o -name "*.mp4" -o -name "*.mp3"; }
for us in /home/*
do
if [ -d "$us" ]; then
N_MP3=$(lt "$us" | grep "\.mp3$" | wc -l)
fi
done
$lt=...
будучи неверным в сторону, первый подход имеет так много проблем, что его даже не стоит предлагать. Используйте функцию для того, для чего они предназначены.
LT
не является определением функции; он содержит результат запускаfind
немедленно.