语法问题。如果我在目标目录中有许多子目录,并且我想将sub的名称输出到文本文件中,我可以轻松运行:
ls > filelist.txt
在目标上。但是说我的所有潜艇都以7个字符的前缀命名,如:
JR-5426_mydir
JR-5487_mydir2
JR-5517_mydir3
...
我只想要前缀。是否有“ls”选项,每行只输出n个字符?
答案 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