如何加入多行文件名为一个自定义分隔符?

我想将ls -1的结果加入到一行中,并使用我想要的任何内容来分隔它。

有什么标准的Linux命令可以用来实现这个目标吗?

292956 次浏览

如果你的xargs版本支持-d标志,那么这应该可以工作

ls  | xargs -d, -L 1 echo

-d是分隔符标志

如果没有-d,那么可以尝试以下操作

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

第一个xargs允许您指定分隔符,在本例中为逗号。

编辑:简单的“__abc1”;如果您希望分隔符为逗号

啊,力量和简单!

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

改变逗号""去任何你想去的地方。请注意,这包括一个“结尾逗号”;(对于以换行符结尾的列表)

你可以使用:

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

为了避免tr的换行符混淆,我们可以在ls中添加-b标志:

ls -1b | 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

在Bash 4中使用readarray(又名mapfile):

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

感谢gniourf_gniourf的建议。

就bash

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

设置IFS和使用"$*"的组合可以做你想做的事情。我使用了一个subshell,所以我不会干扰这个shell的$IFS

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

为了捕获输出,

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

类似于第一个选项,但省略了后面的分隔符

ls -1 | paste -sd "," -

当连接到管道时,ls产生一个列输出,因此-1是多余的。

下面是另一个使用内置join函数的perl答案,该函数不留下尾随分隔符:

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

模糊的-0777使perl在运行程序之前读取所有输入。

不留下尾随分隔符的Sed替代方法

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

我觉得这个很棒

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

ORS是“输出记录分隔符”,所以现在你的行将用逗号连接。

这个命令是为PERL爱好者准备的:

ls -1 | perl -l40pe0

这里的40是空格的八进制ascii码。

-p将逐行处理并打印

-l将负责用我们提供的ASCII字符替换尾随的\n。

-e是通知PERL我们正在执行命令行。

0表示实际上没有命令要执行。

Perl -e0与Perl -e ' '相同

不要白费力气。

ls -m

它就是这么做的。

ls有选项-m,用", "、逗号和空格分隔输出。

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

将此结果输送到tr以删除空格或逗号,将允许您再次将结果输送到tr以替换分隔符。

在我的例子中,我将分隔符,替换为分隔符;

;替换为任何你喜欢的一个字符分隔符,因为tr只考虑作为参数传入的字符串中的第一个字符。

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

解释:

-e -表示要执行的命令 :a -是一个
的标签 /$/N -定义当前和(N)下一行
的匹配范围 s/\n/\\n/; -用\n
替换所有EOL ta; -如果匹配成功,goto标记a

取自我的博客

解析ls一般为不建议,所以另一种更好的方法是使用find,例如:

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

或者使用findpaste:

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

对于一般的多行连接(与文件系统无关),检查:Unix命令行上简明而可移植的“join”

你可以使用chomp将多行合并成一行:

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

在if语句中加入换行条件。它可以是特殊字符或任何分隔符。

看起来答案已经存在了。

如果你想 a, b, c格式,使用ls -m (Tulains Córdova的回答)

或者如果你想要a b c格式,使用ls | xargs (克里斯·J的回答的简化版本)

或者如果你想要任何其他分隔符,如|,使用ls | paste -sd'|' (Artem的回答的应用)

在majkinetor的回答之上,下面是删除尾随分隔符的方法(因为我还不能在他的回答下评论):

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

只要删除分隔符所需要的尾随字节即可。

我喜欢这种方法,因为我可以使用多字符分隔符+ awk的其他好处:

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

编辑

正如Peter所注意到的,head的原生MacOS版本不支持负字节计数。然而,这是很容易解决的。

首先,安装coreutils。GNU核心实用程序是GNU操作系统的基本文件、shell和文本操作实用程序。

brew install coreutils

MacOS提供的命令也以“g”开头安装。例如gls

一旦你这样做了,你可以使用ghead,它有负字节数,或者更好,使别名:

alias head="ghead"

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(n²),因为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

快速Perl版本与尾随斜杠处理:

ls -1 | perl -E 'say join ", ", map {chomp; $_} <>'

解释:

  • perl -E:执行perl的特性支持(例如,…)
  • 说:打印与载体返回
  • join ", ", ARRAY_HERE:用","加入数组
  • 地图{切齿;$_} ROWS:从每一行中删除载体返回并返回结果
  • stdin,每一行都是一个ROW,与map耦合将创建每个ROW的数组

如果你喜欢Python3,你可以这样做(但是请解释为什么你会这样做?):

ls -1 | python -c "import sys; print(','.join(sys.stdin.read().splitlines()))"

上面的Python回答很有趣,但自己的语言甚至可以使输出更好:

Ls -1 | python -c quot;打印(sys.stdin.read () .splitlines ()),