루프를 역순으로 올바르게 수행하는 방법은 for
무엇입니까?
for f in /var/logs/foo*.log; do
bar "$f"
done
파일 이름에서 펑키 한 문자를 깨뜨리지 않는 솔루션이 필요합니다.
답변
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
답변
줄 바꿈을 “펑키 문자”로 간주하지 않는 한 다음을 시도하십시오.
ls /var/logs/foo*.log | tac | while read f; do
bar "$f"
done
답변
공백으로 구분 된 문자열 목록을 반복하는 방법을 알아내는 사람은 다음과 같습니다.
reverse() {
tac <(echo "$@" | tr ' ' '\n') | tr '\n' ' '
}
list="a bb ccc"
for i in `reverse $list`; do
echo "$i"
done
> ccc
> bb
> a
답변
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
대안으로 사용 된다는 점도 언급해야합니다 . 당신도 그것을 확인할 수 있습니다.
뭔가 빠졌을 수 있으므로 다른 사람들이 차임해야합니다.
답변
귀하의 예에서 여러 파일을 반복하고 있지만 배열을 반복하거나 순서를 거꾸로 뒤집을 수있는 일반적인 제목으로 인해이 질문을 발견했습니다.
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로 변경하여 해결할 수 있습니다 (그러나 일단 수정 한 후에는 내 컴퓨터에서 작동하기 때문에 얼마나 정확한지 기억하지 못합니다). 오류 메시지가 표시되고 해결 방법을 찾을 수없는 경우 의견으로 게시하여 문제 해결에 도움을 줄 수 있습니다.
답변
ls -r
@David Schwartz가 언급 한 것처럼 쉬운 방법을 사용 하고 있습니다.
for f in $(ls -r /var/logs/foo*.log); do
bar "$f"
done