我有如下文件列表:
[root@ods1 backup]# ls -l
total 93892810
-rw-r----- 1 root root 651248 Feb 17 08:34 abc_def_g_17-02-2022.sql
-rw------- 1 root root 665248 Mar 23 08:46 bbc_23-03-2022.sql
-rw-r----- 1 root root 676992 Apr 04 16:52 zz_b_04-04-2022.sql
我需要实现的是:
abc_def_g
bbc
zz_b
我尝试这样做,但没有成功:
ls -l | awk '{print $9}' | cut -d '_' -f1-2
我怎样才能实现这个目标?获取直到最后一行的任何一系列命令_性格应该胜任这项工作。
编辑:此命令在 CentOS 8 中执行。
答案1
到不解析ls
,您可以使用简单的loop
andshell
语法:
for f in *; do echo "${f%_*}"; done
如果您需要进一步处理该列表(并且您有一个能够使用数组的 shell),您可以将项目添加到数组中:
tokens=()
for f in *; do tokens=("${tokens[@]}" "${f%_*}"); done
echo "${tokens[@]}"
或者不使用循环,直接声明数组:
files=(*)
tokens=("${files[@]%_*}")
#or
for token in "${files[@]%_*}"; do echo "$token"; done
答案2
你可以尝试这样的事情:
ls|awk -F_ '{NF-=1}1' OFS=_
这里的技巧是将字段数量减一(删除最后一个字段)
答案3
在zsh
shell 中:
print -r -C1 -- *_*.sql(Ne['REPLY=${REPLY%_*}'])
*_*.sql
这使用了一个 glob 限定符,通过删除最后一个下划线之后的所有内容(包括最后一个下划线)来修改与给定的 glob 模式匹配的名称。实际替换是使用标准参数替换进行的。
如果您想使用生成的字符串执行除打印之外的其他操作,请使用通配模式,而不使用 ,print
在有意义的地方(例如,在for
循环中或作为其他命令的参数)。不要将print
上面的命令放入命令替换中!
答案4
$ awk 'BEGIN{for (i=1;i<ARGC;i++) { f=ARGV[i]; sub(/_[^_]*$/,"",f); print f }; delete ARGV}' *
abc_def_g
bbc
zz_b
即使您的文件名包含换行符或任何其他字符,这也可以工作。