glob을 통해 파일 목록을 되돌리는 방법이 있습니까?
따라서 다음과 같은 결과를 얻게 됩니다.
ls -r *
쉘 스크립트에서 이것을 사용하고 있는데 shellcheck
계속 불평합니다.
^---------^ SC2045: 반복 ls 출력이 취약합니다. 글로벌을 사용하세요.
답변1
다루기 힘든
셸을 사용하면 (순서), (역과 동일) 및 (숫자의 경우) glob 한정자를 사용하여 zsh
glob의 정렬 순서를 사용자 정의 할 수 있습니다.oC
OC
^oC
n
인용하다 info zsh qualifier
:
oC
파일 이름이 정렬되는 방식을 지정합니다. C 이면 이름별로 정렬 되고, ,
n
이면L
파일 크기(길이)별로 정렬l
됩니다 . 수정 또는 inode 변경이 있는 경우, 하위 디렉터리의 파일은 모든 검색 수준에서 현재 디렉터리의 파일보다 먼저 나타납니다. 이는 동일한 디렉터리의 파일 이름을 정렬하기 위해 " "와 같은 다른 조건과 함께 사용하는 것이 가장 좋습니다 . 정렬이 수행됩니다. , , age 는 현재 시간과 비교되므로 목록의 첫 번째 이름이 가장 어린 파일입니다. 또한 수정자 와 가 사용되므로 ' '는 심볼릭 링크 바로 다음에 파일 크기의 내림차순으로 모든 파일 목록을 제공합니다. 사용하지 않는 한 여러 순서 지정자가 관계를 해결하는 것처럼 보일 수 있습니다.a
m
c
d
odon
N
a
m
c
^
-
*(^-oL)
oN
glob 한정자를 사용 하지 않는 한 기본 정렬은
n
(이름 기준)이며 , 이 경우에는 (정렬되지 않음)입니다.Y
N
oe
그리고o+
특별한 경우입니다. 각각 뒤에는e
glob 한정자와 glob 한정자로+
구분된 쉘 코드가 옵니다(위 참조). 코드는 일치하는 각 파일에 대해 실행되며 매개변수는REPLY
항목의 파일 이름으로 설정되고 코드는 어떤 방식으로든 매개변수를 수정해야globsort
합니다 . 반환 시 파일 이름 대신 인수 값을 정렬할 문자열로 사용합니다. 다른 정렬 연산자와 달리 및는 반복될 수 있지만 모든 glob 표현식에 나타날 수 있는 모든 유형의 정렬 연산자의 최대 개수는 12개입니다.zsh_eval_context
REPLY
oe
o+
따라서 알파벳 역순으로 파일 목록을 얻으려면 다음을 수행하십시오.
list=(*(NOn))
또는
list=(*(N^on))
N
( (for ) 한정자는 여기서도 사용되므로 nullglob
일치하는 파일이 없으면 목록이 비어 있게 됩니다.)
수정 시간을 기준으로 역순으로 정렬된 목록의 경우(예 ls -rt
: ):
list=(*(NOm))
o
O
zsh를 사용하면 및 매개변수 확장 플래그를 사용하여 배열 요소를 정렬 할 수도 있습니다 .
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 '' array
NUL로 구분된 레코드 목록을 배열로 읽어옵니다.
GNU 구현의 경우 ls
또 다른 접근 방식은 다음과 같습니다.
eval "list=($(ls --quoting-style=shell-always -r))"
여기서 ls --quoting-style=shell-always
작은따옴표를 사용하여 파일 이름을 인용합니다(그리고 \'
작은따옴표 외부에 작은따옴표 자체를 인용합니다).
이 접근 방식은 또한 작동합니다 yash
(모든 파일 이름이 로케일에서 유효한 텍스트라고 가정). 그러나 ksh93
의 경우 변수를 미리 배열로 선언해야 합니다( 사용 ). 그렇지 않으면 출력이 제공되지 않으면 복합으로 생성됩니다. 대신 변수는 배열 변수가 아닙니다.zsh
mksh
ksh93
typeset -a list
ls
$list
ls
ast-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
가 없습니다 . 현재 디렉터리에 숨겨지지 않은 파일이 없으면 요소가 하나만 있는 목록이 생성됩니다. 이 문제를 해결하는 일반적인 방법은 다음과 같습니다.nullglob
zsh
(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 *
이 명령과 마찬가지로 ls
glob과 일치하는 모든 디렉터리의 내용이 나열됩니다 *
.
일치하는 항목이 없으면 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
주어진 및 쉘만 사용 printf
및 set
및 eval
).
set -- *
[ $# -gt 1 ] && eval set -- "$(printf "\"\${%s}\" " $(seq "$#" -1 1))"
printf '%s ' "$@"
가능한 경우 nullglob 및 failedglob을 설정하는 것이 합리적입니다.