Bash - glob을 사용하여 역방향 파일 목록 인쇄

Bash - glob을 사용하여 역방향 파일 목록 인쇄

glob을 통해 파일 목록을 되돌리는 방법이 있습니까?

따라서 다음과 같은 결과를 얻게 됩니다.

ls -r *

쉘 스크립트에서 이것을 사용하고 있는데 shellcheck계속 불평합니다.

^---------^ SC2045: 반복 ls 출력이 취약합니다. 글로벌을 사용하세요.

답변1

다루기 힘든

셸을 사용하면 (순서), (역과 동일) 및 (숫자의 경우) glob 한정자를 사용하여 zshglob의 정렬 순서를 사용자 정의 할 수 있습니다.oCOC^oCn

인용하다 info zsh qualifier:

oC

파일 이름이 정렬되는 방식을 지정합니다. C 이면 이름별로 정렬 되고, , n 이면 L파일 크기(길이)별로 정렬 l됩니다 . 수정 또는 inode 변경이 있는 경우, 하위 디렉터리의 파일은 모든 검색 수준에서 현재 디렉터리의 파일보다 먼저 나타납니다. 이는 동일한 디렉터리의 파일 이름을 정렬하기 위해 " "와 같은 다른 조건과 함께 사용하는 것이 가장 좋습니다 . 정렬이 수행됩니다. , , age 는 현재 시간과 비교되므로 목록의 첫 번째 이름이 가장 어린 파일입니다. 또한 수정자 와 가 사용되므로 ' '는 심볼릭 링크 바로 다음에 파일 크기의 내림차순으로 모든 파일 목록을 제공합니다. 사용하지 않는 한 여러 순서 지정자가 관계를 해결하는 것처럼 보일 수 있습니다.amcdodonNamc^-*(^-oL)oN

glob 한정자를 사용 하지 않는 한 기본 정렬은 n(이름 기준)이며 , 이 경우에는 (정렬되지 않음)입니다.YN

oe그리고 o+특별한 경우입니다. 각각 뒤에는 eglob 한정자와 glob 한정자로 +구분된 쉘 코드가 옵니다(위 참조). 코드는 일치하는 각 파일에 대해 실행되며 매개변수는 REPLY항목의 파일 이름으로 설정되고 코드는 어떤 방식으로든 매개변수를 수정해야 globsort합니다 . 반환 시 파일 이름 대신 인수 값을 정렬할 문자열로 사용합니다. 다른 정렬 연산자와 달리 및는 반복될 수 있지만 모든 glob 표현식에 나타날 수 있는 모든 유형의 정렬 연산자의 최대 개수는 12개입니다.zsh_eval_contextREPLYoeo+

따라서 알파벳 역순으로 파일 목록을 얻으려면 다음을 수행하십시오.

list=(*(NOn))

또는

list=(*(N^on))

N( (for ) 한정자는 여기서도 사용되므로 nullglob일치하는 파일이 없으면 목록이 비어 있게 됩니다.)

수정 시간을 기준으로 역순으로 정렬된 목록의 경우(예 ls -rt: ):

list=(*(NOm))

oOzsh를 사용하면 및 매개변수 확장 플래그를 사용하여 배열 요소를 정렬 할 수도 있습니다 .

list=(*(N))
list_reversed=(${(Oa)list})

즉, 배열 멤버를 $list역순으로 정렬합니다(대문자 사용으로 인해 O) a.

세게 때리다

최신 버전의 bash셸과 GNU를 사용하면 sort역순으로 정렬된 파일 이름 목록을 얻을 수 있습니다.

readarray -td '' list < <(
   shopt -s nullglob
   set -- *
   (($# == 0)) || printf '%s\0' "$@" | sort -rz)

readarray -td '' arrayNUL로 구분된 레코드 목록을 배열로 읽어옵니다.

GNU 구현의 경우 ls또 다른 접근 방식은 다음과 같습니다.

eval "list=($(ls --quoting-style=shell-always -r))"

여기서 ls --quoting-style=shell-always작은따옴표를 사용하여 파일 이름을 인용합니다(그리고 \'작은따옴표 외부에 작은따옴표 자체를 인용합니다).

이 접근 방식은 또한 작동합니다 yash(모든 파일 이름이 로케일에서 유효한 텍스트라고 가정). 그러나 ksh93의 경우 변수를 미리 배열로 선언해야 합니다( 사용 ). 그렇지 않으면 출력이 제공되지 않으면 복합으로 생성됩니다. 대신 변수는 배열 변수가 아닙니다.zshmkshksh93typeset -a listls$list

lsast-open 구현도 옵션을 지원 하지만 인용 형식을 --quoting-style=shell-always사용하므로 모든 로케일에서 사용하기에 안전하지 않습니다.$'...'

POSIX적으로

POSIXly, 배열을 sh뒤집으 려면 다음을 수행할 수 있습니다."$@"

eval "set -- $(awk 'BEGIN {for (i = ARGV[1]; i; i--) printf " \"${"i"}\""}' "$#")"

아이디어는 3개의 요소가 있을 set -- "${3}" "${2}" "${1}"때 출력과 같은 awk 출력을 갖는 것입니다."$@"

따라서 파일 목록을 역순으로 얻으려면 다음을 수행하십시오.

set -- *
eval "set -- $(awk 'BEGIN {for (i = ARGV[1]; i; i--) printf " \"${"i"}\""}' "$#")"
echo file list:
printf ' - %s\n' "$@"

POSIX에는 동등한 옵션( 발명품), zsh의 glob 한정자 또는 ksh93의 glob 연산자 sh가 없습니다 . 현재 디렉터리에 숨겨지지 않은 파일이 없으면 요소가 하나만 있는 목록이 생성됩니다. 이 문제를 해결하는 일반적인 방법은 다음과 같습니다.nullglobzsh(N)~(N)*

set -- [*] *
case "$1$2" in
  ('[*]*') shift 2;;
  (*)      shift;;
esac

여기서 [*]"and"의 조합은 *"a"와 구별되는 *방법 입니다.불일치( [*]으로도 확장됨 [*]) 및 리터럴 이름의 파일 *( [*]으로도 확장됨 *)입니다.


어쨌든, 쉘이 확장을 전달하는 방법 ls과 같이 정렬 할 파일 이름 목록을 전달하는 경우 옵션을 사용하고 다음을 사용하여 옵션 끝을 표시 해야 합니다 .ls -r **-d--

ls -rd -- *

그러나 파일 이름은 줄 바꿈으로 구분되고 줄 바꿈은 파일 이름의 모든 문자만큼 유효하기 때문에 이 출력은 여전히 ​​안정적으로 후처리될 수 없습니다.

답변2

이 질문은 파일 이름 globbing 패턴을 다시 구현하는 것이 아니라 생성된 목록을 뒤집는 것에 관한 것이라고 가정합니다 ls -r.

위치 매개변수에 대한 전역 일치 결과를 가져옵니다. 예를 들면 다음과 같습니다.

set -- *

그런 다음 목록을 반대로 바꿉니다.

names=()
for name do
    shift
    names[$#]=$name
done

names그러면 반전된 와일드카드 패턴의 일치 항목을 포함하는 이름의 배열이 생성됩니다 *.

위치 인수(일치 결과)를 순서대로 반복하고 각 항목에 대해 반전된 목록의 위치에 삽입하여 반전이 수행됩니다. $#는 위치 인수(와일드카드 패턴과 일치)의 수이며 shift해당 목록에서 하나를 제거하고 $#각 반복마다 1씩 감소하므로 위치 인수 목록의 시작 부분부터 배열 끝까지 요소를 삽입합니다 names.

names배열이 있으면 인쇄하십시오.

printf '%s\n' "${names[@]}"

...아니면 필요한 모든 작업을 수행하세요.

이것은 것이다아니요ls -r *이 명령과 마찬가지로 lsglob과 일치하는 모든 디렉터리의 내용이 나열됩니다 *.

일치하는 항목이 없으면 bash패턴을 확장하지 않은 상태로 둡니다 . 활성화 시 이름과 일치하지 않는 패턴을 완전히 제거하는 shopt -s nullglob셸을 설정하는 옵션 입니다. nullglob숨겨진 이름을 일치시키려면 추가 셸 dotglob옵션을 설정하세요.

답변3

어떤 쉘을 사용하고 있는지 말하지 않았으며 영숫자 오름차순 이외의 작업을 수행하는 쉘을 본 적이 없습니다. 따라서 이 작업을 수행하려면 ls, sort또는 이와 유사한 것을 사용해야 합니다 . 바라보다쉘체크 위키반복의 출력이 ls취약한 이유와 이를 해결하는 방법 기본적으로 주목해야 할 두 가지 주요 문제가 있습니다. 1) 디렉토리가 비어 있을 때 기본적으로 echo *인쇄됩니다 . *2) 파일 이름에 공백이 포함되어 있으면 입력 내용을 읽는 데 혼란을 줄 수 있습니다. (1)의 경우 bash를 사용하는 경우 이 옵션을 설정해야 합니다 nullglob. (2)의 경우 다음과 같은 내용을 작성하고 싶을 수도 있습니다.

ls -1r | while read filename; do
    ...
done

sh(다시 말하지만 , bash또는 을 사용한다고 가정합니다 zsh.)

답변4

대부분의 쉘에 이식 가능하며 하나의 파일에서 오류를 방지합니다( seq주어진 및 쉘만 사용 printfseteval).

set -- *
[ $# -gt 1 ] && eval set -- "$(printf "\"\${%s}\" " $(seq "$#" -1 1))"
printf '%s '   "$@"

가능한 경우 nullglob 및 failedglob을 설정하는 것이 합리적입니다.

관련 정보