Вы не должны использовать ls
в сценарии оболочки.Вывод ls
предназначен для потребления человеком * только 1003 * и никогда не должен использоваться в качестве ввода для другой команды.
Во-первых, правильное решение вашей проблемы.
#!/usr/bin/env bash
pat="$1"
while IFS= read -r -d '' file ; do
echo "$file"
done < <(find . -maxdepth 1 -name "$pat" -print0)
Это предполагает, что у вас нет особых требований к порядку или формату имени.Вы можете сослаться на этот ответ , если вам нужно сделать заказ, например ls -t
.
Ваша проблема распространена, и я называю это "Кто что видит?"проблема.Вы говорите myscript.sh E*
и ожидаете, что литерал E*
будет передан в ваш скрипт, но на самом деле, поскольку этот аргумент не заключен в кавычки, glob будет расширен на bash
до вызова вашего скрипта, такваш скрипт видит все файлы в текущем каталоге, имена которых начинаются с E
.
. Как вы заметили, аргумент "в кавычках" исправляет это.Это связано с тем, что bash
не выполняет какого-либо специального расширения внутри одинарных кавычек, поэтому теперь ваш сценарий видит E*
буквально.Вы фактически избежали *
, поэтому bash
не расширит его, пока не передаст его в сценарий.Сделать это без использования кавычек можно с помощью обратного слэша-экранирования *
myscript.sh E\*
Но лучшим решением будет позволить bash
расширить глобус и изменить скрипт для обработки нескольких аргументов файла.,Например:
#!/bin/bash
data=("$(ls -trh "$@")")
for entry in "${data[@]}"
do
echo "${entry}"
done
Здесь я предполагаю, что все аргументы будут именами файлов.Я изменил data
в массив и добавил кавычки для всех расширений, чтобы правильно сохранить пробелы.Это решение по-прежнему неверно, потому что оно анализирует ls
выходные данные, но теперь вы, вероятно, получаете ожидаемое поведение без кавычек E*
myscript.sh E*
В общем случае вы должны всегда цитируйте расширение переменных в сценариях оболочки, потому что это, вероятно, делает то, что вы ожидаете (а расширение без кавычек, вероятно, делает , а не !)