명령 실행 및 리디렉션 순서

명령 실행 및 리디렉션 순서

제가 만들고 있는 bash 스크립트의 경우 디렉터리에서 최신 2개 파일을 제외한 모든 파일을 삭제해야 합니다.

나는 ls -tUr > somefile.txt최신 2개를 사용하고 추적하여 다른 곳으로 옮긴 rm *다음 다시 옮기기로 결정했습니다.

어떤 이유로 실제로 명령을 사용하는 것이 엉망인 부분이 somefile.txt(파일의 나머지 부분에) 나타납니다 .somefile.txttail

그래서 내 질문은 논리적으로 ls현재 폴더/파일이 반환된 다음 로 리디렉션되지만 분명히 실행하기 전에 존재해야 하기 somefile.txt때문에 이런 일이 발생하지 않는다는 것 입니다 .somefile.txtls

답변1

이는 "왜 이런 일이 발생하는가?"라는 질문에 대한 답변입니다.

예, 실제로 somefile.txt실행되기 전에 생성됩니다.ls

$ utility >file

가장 먼저 일어나는 일은 쉘이 리디렉션을 인식하고 생성 file(또는 이미 존재하는 경우 잘라내기)하는 것입니다.그 다음에utility표준 출력 스트림은 실행될 때 들어갑니다 file.

유틸리티는 일반적으로 표준 출력이 어디로 가는지 모르거나 신경 쓰지 않습니다(예를 들어 일부 유틸리티는 lsTTY인지 확인하고 이에 따라 동작을 변경합니다). 따라서 일반 출력 파일, 파이프에 쓰는지 여부는 중요하지 않습니다. , 장치 파일 또는 소켓. 물론 상관없어요만들다이 파일. 따라서 셸의 작업은 프로세스가 시작되기 전에 파이프가 제 위치에 있는지 확인하는 것입니다. 여기에는 file위의 예에 지정된 파일을 생성하거나 자르는 작업이 포함됩니다.

최신 파일을 제외한 모든 파일을 삭제하는 질문에 대한 답변은 "가장 오래된 파일 삭제"

답변2

Kusalananda는 이미 somefile.txt다음 결과가 나온 이유에 대한 귀하의 질문에 답변했지만ls만들어진최근 해결된 링크 문제로 파일수정됨대신 파일.

첫째, 출력을 파일에 쓸 필요가 없습니다. 명령은 서로 직접 상호 작용할 수 있으며 이것이 바로 파이프의 목적입니다.

여기에서 다음을 수행할 수 있습니다.

ls -tU | tail -n +3 | xargs echo rm -f -- # echo for dry-run

tail그러나 이는 행과 (인용될 수 있는) 단어에서 작동 xargs하고 파일 이름이 둘 중 하나라고 보장할 수 없기 때문에 일반적인 경우에는 결함이 있습니다 . 유효한 텍스트라는 보장도 없습니다. 파일 이름에 유효한 문자를 형성하지 않는 공백, 개행, 따옴표, 백슬래시 또는 바이트 시퀀스가 ​​포함되어 있지 않은 경우에만 올바르게 작동합니다.

시스템이 FreeBSD(사용법에서 알 수 있듯이)인 경우 다음과 같이 안정적으로 구문 분석할 수 있는 출력 형식을 -U사용할 수 있습니다 .json

ls --libxo=json -Ut |
  perl -MJSON::PP -l0 -0777 -ne '
    @files = map {$_->{name}} @{
      decode_json($_)->{"file-information"}->{directory}->[0]->{entry}
    };
    print for @files[2..$#files]' | xargs -0 echo rm -f --

관련 정보