ls의 출력을 파일로 리디렉션하면 파일 이름이 파일에 포함됩니다. 이것을 어떻게 피할 수 있습니까?

ls의 출력을 파일로 리디렉션하면 파일 이름이 파일에 포함됩니다. 이것을 어떻게 피할 수 있습니까?

관찰하다:

$ ls
$ ls > list
$ cat list
list

ls이는 파일에 대한 리디렉션을 실행할 때 list이미 시작되었고 list파일이 생성되었음을 나타내는 것 같습니다 . 어쨌든, 그것은 충분히 좋은 설명이지만, 질문은: 어떻게 이런 일이 발생하지 않도록 방지할 수 있습니까? 내가 기대하는 것은 ls그것의 출력을 실행하고 덤프하는 것인데 list, 이것이 바로 내가 원하는 것입니다.

답변1

알다시피 파일은 ls실행되기 전에 생성됩니다. 이는 쉘이 작업 순서를 처리하는 방식 때문입니다. 하기 위해서

ls > file

케이싱 필요만들다 file그런 다음 stdout이 이를 가리키도록 설정하고 마지막으로 프로그램을 실행합니다 ls.

따라서 몇 가지 옵션이 있습니다.

  1. 다른 디렉터리(예:)에 파일을 생성 /tmp하고 mv최종 디렉터리에 복사합니다.
  2. 숨김 파일( )로 만들고 .file이름을 바꿉니다.
  3. grep출력에서 파일을 제거하는 데 사용됩니다.
  4. 속이다:-)

부정 행위는 다음과 같습니다

x=$(ls) ; printf "%s\n" "$x" > file

결과적으로 출력이 ls변수에 저장되고 이를 작성합니다.

답변2

출력 파일은 시작하기 전에 쉘에 의해 ls생성 됩니다. 다음 방법을 사용하여 이 문제를 해결할 수 있습니다 tee.

ls | tee list

어떠한 경쟁 조건도 완전히 극복하려면 항상

ls | grep -vx 'list' > list

또는 원하는 경우 tee결과를 표시할 수 있습니다.

ls | grep -vx 'list' | tee list

그러나 주석에서 지적했듯이 파일 이름에 이상한 문자가 포함되면 이와 같은 문제가 발생하는 경우가 많습니다. Unix 파일 이름에는 NULand 를 제외한 모든 문자가 포함될 수 있으므로 /출력을 구문 분석하는 것은 ls매우 어렵습니다.

  • 파일 이름이 하나 이상의 \n.
  • grep검색어가 사이에 있으면 필터링이 실패합니다 \n.
  • NUL대신 를 \n사용하여 파일 이름을 구분할 수 있지만 find이를 기존의 정렬된 줄 바꿈 구분 출력과 같은 것으로 변환하는 것은 어려울 수 있습니다 ls.
  • 출력 파일 이름이 이미 존재하는 경우 목록에서 제거하는 것이 올바르지 않을 수 있습니다.

따라서 실제로 작동하는 유일한 방법은 출력 파일을 다른 곳에 생성하여 해당 위치로 옮기는 것입니다. 절대 사용하지 않을 경우 ls -a다음과 같이 작동합니다.

ls > .list && mv .list list

ls -athen을 사용하는 경우 .list출력에는 표시되지만 디렉터리에는 더 이상 존재하지 않을 수 있습니다. 따라서 예를 들어 /tmp중간 결과를 저장하기 위해 다른 디렉터리를 사용하게 됩니다 . 물론 항상 사용하면 문제가 발생하므로 /tmp스크립트를 작성할 수 있습니다.

#!/bin/sh
OUTDIR='/tmp'
if [ "${PWD}" = '/tmp' ]; then
  OUTDIR="${HOME}"
fi
ls > "${OUTDIR}/list" && mv "${OUTDIR}/list" list

그러나 이는 이 작업에 비해 너무 복잡해 보입니다.

그러나 문제의 전체 원인은 명령이 시작되기 전에 쉘이 출력 파일을 생성한다는 것입니다. 우리는 이것을 고려하여 쉘이 우리를 위해 파일을 나열하도록 할 수 있습니다. 그렇다면 전혀 필요하지 않습니다 ls!

printf '%s\n' * > list

이는 디렉터리에 인수 목록에 맞지 않는 파일이 너무 많아질 때까지 작동합니다.

답변3

당신은 그것을 사용할 수 있습니다 moreutils sponge:

ls | sponge list

또는 다음을 사용하여 zsh:

cp =(ls) list

GNU 사용 ls:

ls -I list > list

(이전에 파일이 호출된 경우에는 list해당 파일이 나열되지 않음을 의미합니다.)

출력은 어쨌든 정렬 되므로 ls다음을 사용할 수도 있습니다(파일 이름에 개행 문자가 포함되어 있지 않다고 가정).

ls | sort -o list

또는 이중 정렬을 피하기 위해 nsorted를 ls지원하는 경우 (일부 구현에는 다른 것에 대한 a가 있음 에 유의):-UUls-U

ls -U | sort -o list

답변4

크레딧의 일부/대부분은 @StephenHarris에게 전달됩니다…

echo "`ls`" > list

동등하다

echo "$(ls)" > list

관련 정보