是否有“ls”选项限制文件名字符?

时间:2014-12-08 17:12:10

标签: linux unix

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

ls > filelist.txt

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

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

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

2 个答案:

答案 0 :(得分:3)

不要在任何程序化环境中使用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的前缀作为

发出
$'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

答案 1 :(得分:1)

不,您使用cut命令:

ls | cut -c1-7