如何将多行文件名连接到一个自定义分隔符?

Jav*_*cky 397 linux bash shell merge parsing

我希望将结果加入ls -1到一行中并用我想要的任何内容划分它.

我可以使用任何标准的Linux命令来实现这一目标吗?

小智 625

与第一个选项类似,但省略了尾随分隔符

ls -1 | paste -sd "," -
Run Code Online (Sandbox Code Playgroud)

  • 就像一个注释,我尝试的粘贴版本在结尾处需要一个" - "参数来告诉它从STDIN读取.例如`ls -1 | paste -s -d":" - `不确定这是否适用于所有版本的粘贴 (28认同)
  • 这个更好,因为它允许空分隔符:) (4认同)
  • 注意`paste`默认为`-`(标准输入),至少在我的`paste(GNU coreutils)8.22`上. (2认同)
  • 我只是赞成它,这是现在它与选定的答案具有相同的选票。这就是答案。没有尾随分隔符 (2认同)
  • 这样,分隔符只能是单个字符。 (2认同)

zaf*_*zaf 355

编辑:只需" ls -m "如果你想要你的分隔符是逗号

啊,力量和简洁!

ls -1 | tr '\n' ','
Run Code Online (Sandbox Code Playgroud)

将逗号" , " 更改为您想要的任何内容.请注意,这包括"尾随逗号"

  • +1,但更精细的版本应该以不同的方式处理 (45认同)
  • @Chris:使用结束标记字符,你的`sed`可能会更高效:`ls -1 | tr"\\n"","| sed's /,$ //'; 回声''` (7认同)
  • 如果文件名中包含一个`\n`,这也将替换它. (5认同)
  • 在 `tr` 之后使用 `sed` 似乎只是删除最后一个符号似乎不合理。我用`ls -1 | tr '\n' ',' | 头-c -1` (4认同)
  • @ShreevatsaR:他的意思是不附加一个尾随","我相信.像这样`ls -1 | tr"\\n"","| sed's/\(.*\),/\1 /'` (3认同)

Pau*_*ce. 26

这将使用换行符替换最后一个逗号:

ls -1 | tr '\n' ',' | sed 's/,$/\n/'
Run Code Online (Sandbox Code Playgroud)

ls -m 包括屏幕宽度字符的换行符(例如80).

主要是Bash(只是ls外部):

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

在Bash 4中使用readarray(aka mapfile):

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

感谢gniourf_gniourf的建议.


maj*_*tor 19

我觉得这个很棒

ls -1 | awk 'ORS=","'
Run Code Online (Sandbox Code Playgroud)

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

  • 这不排除尾随分隔符. (6认同)
  • 由于处理多字符记录分隔符(例如,"OR"),这尤其令人敬畏 (4认同)

gle*_*man 14

设置IFS和使用的组合"$*"可以做你想要的.我正在使用子shell,所以我不会干扰这个shell的$ IFS

(set -- *; IFS=,; echo "$*")
Run Code Online (Sandbox Code Playgroud)

要捕获输出,

output=$(set -- *; IFS=,; echo "$*")
Run Code Online (Sandbox Code Playgroud)

  • 如果给`set`一堆参数但没有选项,它会设置位置参数($ 1,$ 2,...).` - `是保护`set`,以防第一个参数(或本例中的文件名)恰好以破折号开头.请参阅`help set`中`--`选项的说明.我发现位置参数是处理事物列表的便捷方式.我也可以用数组实现它:`output = $(files =(*); IFS =,; echo"$ {files [*]}")` (3认同)
  • 你有关于`set`如何运作的更多信息吗?看起来有点像伏都教给我.通过`man set`浅看也没有给我很多信息. (2认同)

ken*_*orb 13

ls一般解析,所以替代更好的方法是使用find,例如:

find . -type f -print0 | tr '\0' ','
Run Code Online (Sandbox Code Playgroud)

或者通过使用findpaste:

find . -type f | paste -d, -s
Run Code Online (Sandbox Code Playgroud)

对于一般连接多行(与文件系统无关),请检查:Unix命令行上的简洁和可移植"join".


Tul*_*ova 9

不要重新发明轮子.

ls -m
Run Code Online (Sandbox Code Playgroud)

它正是如此.

  • 使用tr将删除文件名中的空格.最好使用`sed'/,/,/ g` (2认同)

Ale*_*nek 9

除了 majkinetor 的回答之外,这里是删除尾随分隔符的方法(因为我还不能在他的回答下发表评论):

ls -1 | awk 'ORS=","' | head -c -1
Run Code Online (Sandbox Code Playgroud)

只需删除与分隔符数量相同的尾随字节即可。

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

ls -1 | awk 'ORS=", "' | head -c -2
Run Code Online (Sandbox Code Playgroud)

编辑

正如 Peter 所注意到的,本机 MacOS 版本的 head 不支持负字节数。然而,这可以很容易地修复。

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

brew install coreutils
Run Code Online (Sandbox Code Playgroud)

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

完成此操作后,您可以使用ghead具有负字节数的哪个,或者更好的是,使用别名:

alias head="ghead"
Run Code Online (Sandbox Code Playgroud)


gho*_*g74 7

只是打击

mystring=$(printf "%s|" *)
echo ${mystring%|}
Run Code Online (Sandbox Code Playgroud)

  • 稍微高效的是使用"printf -v mystring"%s |"*" - 避免使用$()的fork (5认同)

Sid*_*han 7

此命令适用于PERL粉丝:

ls -1 | perl -l40pe0
Run Code Online (Sandbox Code Playgroud)

这里40是空间的八进制ascii代码.

-p将逐行处理并打印

-l将负责用我们提供的ascii字符替换尾部\n.

-e是告知PERL我们正在执行命令行.

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

perl -e0与perl -e'相同

  • "gzip压缩不会损害Perl的可读性." :) (2认同)

小智 6

为了避免tr的潜在新行混淆,我们可以将-b标志添加到ls:

ls -1b | tr '\n' ';'
Run Code Online (Sandbox Code Playgroud)


zha*_*zha 6

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
Run Code Online (Sandbox Code Playgroud)

注意

这在复杂性上是线性的,在所有行都附加到 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
Run Code Online (Sandbox Code Playgroud)


Ana*_*kar 5

sed -e :a -e '/$/N; s/\n/\\n/; ta' [filename]
Run Code Online (Sandbox Code Playgroud)

解释:

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

摘自我的博客


plh*_*lhn 5

看起来答案已经存在。

如果您想要 a, b, c格式,请使用ls -mTulains Córdova 的回答

或者,如果您想要a b c格式,请使用ls | xargsChris J's answer 的简化版本)

或者,如果您想要任何其他分隔符,例如|,请使用ls | paste -sd'|'Artem 的答案的应用)