답변:
bash 또는 ksh에서 파일 이름을 배열에 넣고 해당 배열을 역순으로 반복하십시오.
files=(/var/logs/foo*.log)
for ((i=${#files[@]}-1; i>=0; i--)); do
bar "${files[$i]}"
done
위의 코드는 ksh_arrays
옵션이 설정되어있는 경우 (zsh 에뮬레이션 모드에있는 경우) zsh에서도 작동 합니다. zsh에는 glob 한정자를 통해 일치하는 순서를 바꾸는 간단한 방법이 있습니다.
for f in /var/logs/foo*.log(On); do bar $f; done
POSIX에는 배열이 포함되어 있지 않으므로 이식성을 원한다면 문자열 배열을 직접 저장하는 유일한 옵션은 위치 매개 변수입니다.
set -- /var/logs/foo*.log
i=$#
while [ $i -gt 0 ]; do
eval "f=\${$i}"
bar "$f"
i=$((i-1))
done
i
및 f
; 다만 수행 shift
, 사용 $1
당신을 호출 bar
에, 테스트를 [ -z $1 ]
당신의에서 while
.
[ -z $1 ]
아닙니다 [ -z "$1" ]
(매개 변수가 *
비어 있거나 문자열 이 아닌 경우 ). 그리고 어쨌든 그들은 여기에서 도움이되지 않습니다 : 문제는 반대 순서로 반복하는 방법입니다.
줄 바꿈을 "펑키 문자"로 간주하지 않는 한 다음을 시도하십시오.
ls /var/logs/foo*.log | tac | while read f; do
bar "$f"
done
f
제 상황 에서 변수 를 깨뜨 렸습니다 . 그러나이 대답은 일반 for
회선 을 대체하는 대체 기능으로 작동합니다 .
공백으로 구분 된 문자열 목록을 반복하는 방법을 알아내는 사람은 다음과 같습니다.
reverse() {
tac <(echo "$@" | tr ' ' '\n') | tr '\n' ' '
}
list="a bb ccc"
for i in `reverse $list`; do
echo "$i"
done
> ccc
> bb
> a
tac
GNU coreutils의 일부인 것처럼 충격적 입니다. 그러나 귀하의 솔루션도 좋습니다.
tac
. tac
여기 에 적은 응답 의 수에서 OSX에 tac이없는 것 같습니다. 어떤 경우에는 @arp 솔루션의 변형을 사용하십시오-어쨌든 이해하기가 더 쉽습니다.
find /var/logs/ -name 'foo*.log' -print0 | tail -r | xargs -0 bar
원하는 방식으로 작동해야합니다 (Mac OS X에서 테스트되었으며 아래에주의 사항이 있습니다 ...).
man 페이지에서 찾기 :
-print0
This primary always evaluates to true. It prints the pathname of the current file to standard output, followed by an ASCII NUL character (charac-
ter code 0).
기본적으로 문자열 + glob와 일치하는 파일을 찾고 NUL 문자로 종료합니다. 파일 이름에 줄 바꿈이나 다른 이상한 문자가 포함되어 있으면 find에서 잘 처리해야합니다.
tail -r
파이프를 통해 표준 입력을 가져 와서 반전시킵니다 ( 자세한 내용 은 표준 기본값 인 마지막 10 줄뿐만 아니라 모든 입력을 stdout에 tail -r
인쇄 합니다man tail
).
그런 다음 파이프를 다음에 파이프합니다 xargs -0
.
-0 Change xargs to expect NUL (``\0'') characters as separators, instead of spaces and newlines. This is expected to be used in concert with the
-print0 function in find(1).
여기서, 인수 당신이에서 전달 된 NUL 문자로 구분하여 볼 것으로 기대를 xargs 명령 find
과 함께 반전 tail
.
내주의 사항 : null 종료 문자열로 잘 작동하지 않는다는 것을 읽었습니다tail
. 이것은 Mac OS X에서 잘 작동했지만 모든 * nix에 해당되는 것은 아닙니다. 조심스럽게 밟으십시오.
또한 GNU Parallel 이 종종 xargs
대안으로 사용 된다는 점도 언급해야합니다 . 당신도 그것을 확인할 수 있습니다.
뭔가 빠졌을 수 있으므로 다른 사람들이 차임해야합니다.
tail -r
... 내가 잘못하고 있습니까?
tac
가 대안으로 언급 되었으므로 대신 시도해보십시오
tail -r
OSX에만 적용되며 널로 구분 된 입력이 아니라 개행으로 구분 된 입력을 되돌립니다. 두 번째 솔루션은 전혀 작동하지 않습니다 (입력을 파이핑 ls
하는 중입니다). 안정적으로 작동하게하는 쉬운 수정은 없습니다.
귀하의 예에서 여러 파일을 반복하고 있지만 배열을 반복하거나 순서를 거꾸로 뒤집을 수있는 일반적인 제목으로 인해이 질문을 발견했습니다.
Zsh에서이를 수행하는 방법은 다음과 같습니다.
배열의 요소를 반복하는 경우이 구문을 사용하십시오 ( source )
for f in ${(Oa)your_array}; do
...
done
O
다음 플래그에 지정된 순서를 반대로 바꿉니다. a
일반적인 배열 순서입니다.
@Gilles가 말했듯이 예를 들어와 같이 globbed On
파일을 역순으로 정렬합니다 my/file/glob/*(On)
. 때문 On
이다 "역 이름 순서."
Zsh 정렬 플래그 :
a
배열 순서L
파일 길이l
링크 수m
수정일n
이름^o
역순 ( o
정상 순서)O
역순으로예를 들어 https://github.com/grml/zsh-lovers/blob/master/zsh-lovers.1.txt 및 http://reasoniamhere.com/2014/01/11/outrageously-useful-tips- to-master-your-z-shell /
Mac OSX는 tac
명령을 지원하지 않습니다 . @tcdyl의 솔루션은 for
루프 에서 단일 명령을 호출 할 때 작동 합니다. 다른 모든 경우에는 다음이 가장 간단한 방법입니다.
이 방법은 파일 이름에 줄 바꿈을 지원하지 않습니다. 근본적인 이유는 tail -r
입력을 줄 바꿈으로 구분하여 정렬하는 것입니다.
for i in `ls -1 [filename pattern] | tail -r`; do [commands here]; done
그러나 줄 바꿈 제한을 극복하는 방법이 있습니다. 파일 이름에 특정 문자가 포함되어 있지 않다면 (예 : '=') tr
모든 줄 바꿈을 사용 하여이 문자가 된 다음 정렬 할 수 있습니다. 결과는 다음과 같습니다.
for i in `find [directory] -name '[filename]' -print0 | tr '\n' '=' | tr '\0' '\n'
| tail -r | tr '\n' '\0' | tr '=' '\n' | xargs -0`; do [commands]; done
참고 :의 버전에 따라 문자로 tr
지원하지 않을 수 있습니다 '\0'
. 이것은 일반적으로 로케일을 C로 변경하여 해결할 수 있습니다 (그러나 일단 수정 한 후에는 내 컴퓨터에서 작동하기 때문에 얼마나 정확한지 기억하지 못합니다). 오류 메시지가 표시되고 해결 방법을 찾을 수없는 경우 의견으로 게시하여 문제 해결에 도움을 줄 수 있습니다.
sort -r
앞에 파이프를for
넣거나을 세탁하십시오ls -r
.