我有以下(MWE)shell 脚本foo:
#!/bin/bash
ARGS=("$@") # all arguments
## => if it exists, we need to drop the argument "-D" here
ls -l ${ARGS[@]} | sort -fk8
Run Code Online (Sandbox Code Playgroud)
如果foo使用参数调用-D(参数列表中的位置未知),如何-D从参数列表中删除?unset ARGS[${#ARGS[@]}-1]例如,我发现可以删除最后一个参数,但我不确定参数的传递顺序(所以我首先需要知道参数在哪个位置,然后在提供的情况下将其删除)。
简洁的方法是简单地循环位置参数,将所有参数收集-D到一个数组中,然后用于set --更新参数:
for param; do
[[ ! $param == '-D' ]] && newparams+=("$param")
done
set -- "${newparams[@]}" # overwrites the original positional params
Run Code Online (Sandbox Code Playgroud)
随着zsh,使用${array:#pattern}参数扩展运算符:
$ set foo -D -D bar '' $'a\nb'
$ printf '<%s>\n' "${@:#-D}"
<foo>
<bar>
<>
<a
b>
Run Code Online (Sandbox Code Playgroud)
POSIXly:
for i do
[ "$i" = -D ] || set -- "$@" "$i"
shift
done
printf '<%s>\n' "$@"
Run Code Online (Sandbox Code Playgroud)
顺便说一句,您忘记了引号,--并且-d:
ls -ld -- "$@"
Run Code Online (Sandbox Code Playgroud)
如果你想按修改时间排序,你可以只使用该-t选项,这里用-r(反向)表示最旧:
ls -lrtd -- "$@"
Run Code Online (Sandbox Code Playgroud)
请注意,如果$ARGS是一个空数组,它将列出.. 所以你可以这样做:
[ "$@" -eq 0 ] || ls -lrtd -- "$@"
Run Code Online (Sandbox Code Playgroud)
要根据一天中的小时可靠地排序而不考虑日期,zsh以及ls支持-U不排序的实现:
zmodload zsh/stat # best in ~/.zshrc
bytime() zstat -LA REPLY -F%T +mtime -- $REPLY
ls --full-time -ldU -- .(e{'reply=("$@")'}o+bytime)
Run Code Online (Sandbox Code Playgroud)
像 有限的外壳bash,很难根据这样的任意元数据对文件进行排序。同样,如果您可以访问最近的 GNU 工具,那就稍微容易一些:
[ "$#" -gt 0 ] && (
export LC_ALL=C
printf '%s\0' "$@" |
sed -z 's|^-$|./-|' |
xargs -r0 stat --printf '%y\t%n\0' -- |
sort -zk2,2 |
cut -zf 2-
) | xargs -r0 ls -lUd --
Run Code Online (Sandbox Code Playgroud)
可移植(但仍然在ls -U这里使用非标准),通常更容易诉诸于perl,例如:
perl -MPOSIX -e '
exec qw{ls -ldU --},
map {$_->[1]}
sort {$a->[0] cmp $b->[0]}
map {[strftime("%T", localtime((lstat$_)[9])), $_]}
@ARGV' -- "$@"
Run Code Online (Sandbox Code Playgroud)