쉘 스크립트에서 매개변수 목록에서 매개변수를 제거하는 방법은 무엇입니까?

쉘 스크립트에서 매개변수 목록에서 매개변수를 제거하는 방법은 무엇입니까?

다음 (MWE) 쉘 스크립트가 있습니다 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>

POSIX적으로:

for i do
  [ "$i" = -D ] || set -- "$@" "$i"
  shift
done
printf '<%s>\n' "$@"

--그런데 , 당신은 따옴표를 잊어버렸습니다 -d.

ls -ld -- "$@"

수정 시간별로 정렬하려면 이 -t옵션을 사용할 수 있습니다. 여기서 (역방향)을 사용하면 -r가장 오래된 것부터 의미합니다.

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)

이와 같은 제한된 셸을 사용하면 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' -- "$@"

관련 정보