Как объединить несколько строк имен файлов в один с помощью пользовательского разделителя?

Я хотел бы присоединиться к результату ls -1 в одну строку и разделите ее тем, что я хочу.

есть ли стандартные команды Linux, которые я могу использовать для достижения этого?

19 ответов


аналогично самому первому варианту, но опускает конечный разделитель

ls -1 | paste -sd "," -

редактировать: просто "ls-m " если вы хотите, чтобы ваш разделитель был запятой

Ах, сила и простота !

ls -1 | tr '\n' ','

изменить запятую ", " к чему хочешь. Обратите внимание, что это включает в себя "конечную запятую"


это заменяет последнюю запятую новой строкой:

ls -1 | tr '\n' ',' | sed 's/,$/\n/'

ls -m включает новые строки в символе ширины экрана (например, 80-й).

в основном Bash (только ls внешние):

saveIFS=$IFS; IFS=$'\n'
files=($(ls -1))
IFS=,
list=${files[*]}
IFS=$saveIFS

используя readarray (Он же mapfile) в Баш 4:

readarray -t files < <(ls -1)
saveIFS=$IFS
IFS=,
list=${files[*]}
IFS=$saveIFS

спасибо gniourf_gniourf за предложения.


Я думаю, что это потрясающе

ls -1 | awk 'ORS=" "'

сочетание настроек IFS и использовать "$*" может делать то, что вы хотите. Я использую подсеть, поэтому я не вмешиваюсь в эту оболочку $IFS

(set -- *; IFS=,; echo "$*")

чтобы захватить выход,

output=$(set -- *; IFS=,; echo "$*")

извлечение ls В общем Не рекомендуется, поэтому альтернативный лучший способ-использовать find, например:

find . -type f -print0 | tr '' ','

и с помощью find и paste:

find . -type f | paste -d, -s

для общего соединения нескольких строк (не связанных с файловой системой) проверьте:краткий и портативный "join" в командной строке Unix.


Не изобретайте колесо.

ls -m

Он делает именно это.


просто bash

mystring=$(printf "%s|" *)
echo ${mystring%|}

эта команда предназначена для поклонников PERL:

ls -1 | perl -l40pe0

здесь 40-восьмеричный код ascii для пространства.

- p будет обрабатывать строку за строкой и печатать

- l позаботится о замене trailing \n символом ascii, который мы предоставляем.

- e должен сообщить PERL, что мы выполняем выполнение командной строки.

0 означает, что на самом деле нет, чтобы выполнить команду.

perl-e0 совпадает с perl-e'


чтобы избежать потенциальной путаницы новой строки для tr, мы могли бы добавить флаг-b в ls:

ls -1b | tr '\n' ';'

sed -e :a -e '/$/N; s/\n/\n/; ta' [filename]

объяснение:

-e - обозначает команду для выполнения
:a - это метка
/$/N - определяет область соответствия для текущей и (N)строки ext
s/\n/\n/; - заменяет все EOL на \n
ta; - goto label a, если матч будет успешным

принято от мой блог.


вы можете использовать:

ls -1 | perl -pe 's/\n$/some_delimiter/'

Если ваша версия xargs поддерживает флаг-d, то это должно работать

ls  | xargs -d, -L 1 echo

- d-флаг разделителя

Если у вас нет-d, то вы можете попробовать следующее

ls | xargs -I {} echo {}, | xargs echo

первый xargs позволяет указать разделитель, который является запятой в этом примере.


ls производит один выход столбца при подключении к трубе, поэтому -1 - это лишнее.

вот еще один ответ perl, используя встроенный join функция, которая не оставляет продольный разделитель:

ls | perl -F'\n' -0777 -anE 'say join ",", @F'

непонятных -0777 заставляет perl читать все входные данные перед запуском программы.

альтернатива sed, которая не оставляет разделителя

ls | sed '$!s/$/,/' | tr -d '\n'

похоже, что ответы уже существуют.

если вы хотите используйте ls -m ( ответ Tulains Кордова)

или если вы хотите используйте ls | xargs (simpified версия ответ Криса Джея)

или если вы хотите любой другой разделитель, как | используйте ls | paste -sd'|' (приложение Артем)


путь sed,

sed -e ':a; N; $!ba; s/\n/,/g'
  # :a         # label called 'a'
  # N          # append next line into Pattern Space (see info sed)
  # $!ba       # if it's the last line ($) do not (!) jump to (b) label :a (a) - break loop
  # s/\n/,/g   # any substitution you want

Примечание:

это линейно по сложности, подставляя только один раз после того, как все строки добавляются в пространство шаблона sed.

@AnandRajaseka это ответ, и некоторые другие подобные ответы, такие как здесь, являются O (n2), потому что sed должен делать замену каждый раз, когда новая строка добавляется в пространство шаблона.

Для сравнения

seq 1 100000 | sed ':a; N; $!ba; s/\n/,/g' | head -c 80
  # linear, in less than 0.1s
seq 1 100000 | sed ':a; /$/N; s/\n/,/; ta' | head -c 80
  # quadratic, hung

добавление поверх ответа majkinetor, вот способ удаления конечного разделителя(так как я не могу просто прокомментировать его ответ):

ls -1 | awk 'ORS=","' | head -c -1

просто удалите столько конечных байтов, сколько считает ваш разделитель.

мне нравится этот подход, потому что я могу использовать разделители нескольких символов + другие преимущества awk:

ls -1 | awk 'ORS=", "' | head -c -2

ls параметр -m для разделения продукции с ", " запятая и Пробел.

ls -m | tr -d ' ' | tr ',' ';'

трубопроводы этот результат в tr чтобы удалить пробел или запятую, вы сможете снова передать результат в tr для замены разделителя.

в моем примере я заменяю разделитель , С разделитель ;

заменить ; любой один символ разделителя вы предпочитаете, так как TR учитывает только первый символ в строке вы передаете в качестве аргумента.


вы можете использовать chomp для объединения нескольких строк в одну строку:

perl-e ' while ( ) {if ( / \ $ / ) {chomp; } print ;}' bad0 >test

поместите условие разрыва строки в Оператор if.Это может быть специальный символ или любой разделитель.