Я хочу просмотреть каталог, и для каждого файла, который не является каталогом, я хочу добавить имена вместе и разделить их запятой.
files=""
for f in $(ls ~/Downloads | grep -v ^d)
do
files+="$f"","
done
echo "$files"
здесь папка для загрузки содержит файлы, такие как
this: 01 - Agar Mujhse Mohabbat Hai - www.downloadming.com.mp3
Ожидаемый результат: 01 - Agar Mujhse Mohabbat Hai - www.downloadming.com.mp3
Фактический результат: 01, -, Агар, Mujhse, Mohabbat, Hai, -, www.downloadming.com.mp3
Все решения приветствуются.
files=()
cd ~/Downloads
for file in *; do
[[ -d $file ]] && continue
files+=( "$file" )
done
printf "%s\n" "${files[@]}"
comma_separated=$(IFS=,; echo "${files[*]}")
echo "$comma_separated"
, Как Вы видели, for f in $(ls)
выполняет итерации по эти слова в выводе, не эти строки . Сохраните ls
для того, когда Вы хотите, чтобы человеческие глаза видели файлы и использовали шаблоны имени файла оболочки, когда Вы хотите, чтобы Ваш сценарий сделал что-то с именами файлов.
Более короткое решение: find ~/Downloads -type f -not -name "d*" -printf "%f,"
Использование while read
вместо for
самый безопасный способ, которым я нашел для итерации по спискам имени файла, состоит в том, чтобы передать по каналу к while read
таким образом:
find ~/Downloads -type f | while read filename; do
echo "found file called $filename";
done
, Как Вы видите, это помещает целое имя файла (разделение строками вместо пробела) в имя переменной, которое Вы предоставляете, здесь $filename
.
От исходного вопроса, однако, если то, что на самом деле требуется, является разделенным запятыми списком файлов, тогда Вы не должны даже выполнять итерации, просто использовать tr
для разделители tr anslate строки в запятые:
find ~/Downloads -type f | tr '\n' ','
Это - проблема Внутренний Разделитель полей. Скорее это не проблема, это было разработано тот путь. Это разделяет вход пробелом, так же, как в позиционных параметрах.
Из страницы справочника Bash:
для имени [[в [слово...]];] действительно перечисляют;готово
Список слов после в расширен, генерировав список объектов. Имя переменной определяется к каждому элементу этого списка в свою очередь, и список выполняется каждый раз. Если в слове опущен, для команды выполняет список однажды для каждого позиционного параметра, который устанавливается. Статус возврата является статусом выхода последней команды, которая выполняется. Если расширение объектов после в результатах в пустом списке, никакие команды не выполняются, и статус возврата 0.
Это означает, что это разворачивает результаты выражения в список слов. Это - то, где Внутренний Разделитель полей, $IFS входит. По умолчанию $IFS установлен на пробел (пространство, вкладка и новая строка). Это означает, что поле состоит из всего до (но не включая) эти пробельные символы. Поскольку имена файлов состоят из пробелов, это рассматривает их как несколько различных полей и выполняет цикл однажды для каждого поля. Способ зафиксировать это состоит в том, чтобы скорректировать значение $IFS.
Так, необходимо скорректировать $IFS к чему-то другому, чем пробел. Используя Ваш существующий метод однако не было бы никакого способа сказать, где одно имя файла заканчивается, и другой начинается, если у них всех, оказывается, нет расширений файла. Более легкий способ пойти об этом использовал бы find
утилита как так:
#Save the original IFS
oldifs=$IFS
#Set the new IFS to the ASCII null character \x00
IFS=$(echo -ne "\x00")
files="" #To prevent scoping issues
#Use the find utility to find and print just regular files (not directories),
#and not going further than ~/Downloads (remove '-maxlength 1' to make the
#search fully recursive), then print the filenames in the format
#file1\x00file2\x00file3\x00file4...
#However, since our new IFS is now \x00, the boundary upon which these filenames are
#separated now works as expected
for f in $(find ~/Downloads -maxdepth 1 -type f -print0)
do
files="$files,$f"
done
echo "$files"
#Reset IFS
IFS=$oldifs
Я также хотел бы указать что Ваш оператор ls ~/Downloads | grep -v ^d
вероятно, не делает то, что Вы ожидаете. Это кажется, что Вы пытались фильтровать каталоги, но что на самом деле происходит, вот то, что это отфильтровывает файлы, которые запускаются с 'd'. Это вызвано тем, что Вы не используете длинную форму ls
как ls -l
. ls -l
вывод печати как:
drwxrwxrw- user group SomeDirectory size date_modified filename
тогда как 'ls' печатает просто имена файлов:
SomeDirectory
file1
file2
file3