我有以下(MWE)shell 脚本foo
:
#!/bin/bash
ARGS=("$@") # all arguments
## => if it exists, we need to drop the argument "-D" here
ls -l ${ARGS[@]} | sort -fk8
如果foo
使用参数调用-D
(参数列表中的位置未知),我如何-D
从参数列表中删除?例如,我发现unset ARGS[${#ARGS[@]}-1]
可以删除最后一个参数,但我不确定参数的传递顺序(因此我首先需要知道参数在哪个位置,然后在提供参数时将其删除)。
答案1
简单的方法是简单地循环位置参数,将所有参数收集-D
到一个数组中,然后用于set --
更新参数:
for param; do
[[ ! $param == '-D' ]] && newparams+=("$param")
done
set -- "${newparams[@]}" # overwrites the original positional params
答案2
对于zsh
,使用${array:#pattern}
参数扩展运算符:
$ set foo -D -D bar '' $'a\nb'
$ printf '<%s>\n' "${@:#-D}"
<foo>
<bar>
<>
<a
b>
POSIXly:
for i do
[ "$i" = -D ] || set -- "$@" "$i"
shift
done
printf '<%s>\n' "$@"
顺便说一句,你忘记了引号,--
并且-d
:
ls -ld -- "$@"
如果你想按修改时间排序,你可以使用该-t
选项,这里使用-r
(reverse) 表示最早的在前:
ls -lrtd -- "$@"
请注意,如果$ARGS
是一个空数组,它将列出.
。所以你可以这样做:
[ "$@" -eq 0 ] || ls -lrtd -- "$@"
排序可靠地基于一天中的小时而不考虑日期,并且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)
对于像 这样的有限 shell 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 --
可移植(但仍然使用非标准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' -- "$@"