filelist.txt 在目标上。但是假设我所有的潜艇都以 7 个字符的前缀命名,例-6ren">
gpt4 book ai didi

linux - "ls"是否有限制文件名字符的选项?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:57:55 26 4
gpt4 key购买 nike

语法问题。如果我在目标目录中有许多子目录,并且我想将子目录的名称输出到一个文本文件中,我可以轻松运行:

ls > filelist.txt

在目标上。但是假设我所有的潜艇都以 7 个字符的前缀命名,例如:

JR-5426_mydir
JR-5487_mydir2
JR-5517_mydir3
...

我只想要前缀。 “ls”是否有每行只输出 n 个字符的选项?

最佳答案

不要在任何编程上下文中使用ls;它应该严格用于向人类展示 -- ParsingLs详细说明原因。

在 bash 4.0 或更高版本上,下面将提供文件名前缀的去重列表:

declare -A prefixes_seen=( )     # create an associative array -- aka "hash" or "map"
for file in *; do # iterate over all non-hidden directory entries
prefixes_seen[${file:0:2}]=1 # add the first two chars of each as a key in the map
done
printf '%s\n' "${!prefixes_seen[@]}" # print all keys in the map separated by newlines

就是说,如果您不想要 2 个字符的前缀,而是想要第一个 - 之前的所有内容,您可以编写更简洁的内容:

declare -A prefixes_seen=( )
for file in *-*; do
prefixes_seen[${file%%-*}]=1 # "${file%%-*}" cuts off "$file" at the first dash
done
printf '%s\n' "${!prefixes_seen[@]}"

...如果您不关心重复数据删除:

for file in *-*; do
printf '%s\n' "${file%%-*}"
done

...或者,坚持两个字符的规则:

for file in *; do
printf '%s\n' "${file:0:2}"
done

就是说——如果你想做对,你也不应该使用换行符来分隔文件名字符列表,因为换行符在 POSIX 文件系统的文件名中是有效的。考虑一个名为 f$'\n'oobar 的文件——也就是说,在第二个字符中有一个文字换行符;粗心编写的代码会将 f 视为一个前缀,将 oo 视为第二个前缀,来自这个单一名称。在这种情况下,迭代关联数组前缀(如对重复数据删除答案所做的那样)更安全,因为它不依赖于任何定界符。

为了证明差异——如果不是写

printf '%s\n' "${!prefixes_seen[@]}"

你写的

printf '%q\n' "${!prefixes_seen[@]}"

它将发出假设文件的前缀 f$'\n'oobar as

$'f\n'

代替

f

...下面有一个额外的换行符。


如果你想在程序之间传递文件名列表(或者,在这里,文件名前缀),安全的方法是用 NUL 分隔元素——因为 NUL 是不可能存在的单个字符在有效的 UNIX 路径中。 (文件名也不能包含 /,但路径显然可以)。

NUL 分隔的列表可以这样写:

printf '%s\0' "${!prefixes_seen[@]}"

...并在接收端读回相同的数据结构(接收代码应该用 bash 编写),如下所示:

declare -A prefixes_seen=( )
while IFS= read -r -d '' prefix; do
prefixes_seen[$prefix]=1
done

关于linux - "ls"是否有限制文件名字符的选项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27363215/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com