관찰하다:
$ ls
$ ls > list
$ cat list
list
ls
이는 파일에 대한 리디렉션을 실행할 때 list
이미 시작되었고 list
파일이 생성되었음을 나타내는 것 같습니다 . 어쨌든, 그것은 충분히 좋은 설명이지만, 질문은: 어떻게 이런 일이 발생하지 않도록 방지할 수 있습니까? 내가 기대하는 것은 ls
그것의 출력을 실행하고 덤프하는 것인데 list
, 이것이 바로 내가 원하는 것입니다.
답변1
알다시피 파일은 ls
실행되기 전에 생성됩니다. 이는 쉘이 작업 순서를 처리하는 방식 때문입니다. 하기 위해서
ls > file
케이싱 필요만들다 file
그런 다음 stdout이 이를 가리키도록 설정하고 마지막으로 프로그램을 실행합니다 ls
.
따라서 몇 가지 옵션이 있습니다.
- 다른 디렉터리(예:)에 파일을 생성
/tmp
하고mv
최종 디렉터리에 복사합니다. - 숨김 파일( )로 만들고
.file
이름을 바꿉니다. grep
출력에서 파일을 제거하는 데 사용됩니다.- 속이다:-)
부정 행위는 다음과 같습니다
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 파일 이름에는 NUL
and 를 제외한 모든 문자가 포함될 수 있으므로 /
출력을 구문 분석하는 것은 ls
매우 어렵습니다.
- 파일 이름이 하나 이상의
\n
. grep
검색어가 사이에 있으면 필터링이 실패합니다\n
.NUL
대신 를\n
사용하여 파일 이름을 구분할 수 있지만find
이를 기존의 정렬된 줄 바꿈 구분 출력과 같은 것으로 변환하는 것은 어려울 수 있습니다ls
.- 출력 파일 이름이 이미 존재하는 경우 목록에서 제거하는 것이 올바르지 않을 수 있습니다.
따라서 실제로 작동하는 유일한 방법은 출력 파일을 다른 곳에 생성하여 해당 위치로 옮기는 것입니다. 절대 사용하지 않을 경우 ls -a
다음과 같이 작동합니다.
ls > .list && mv .list list
ls -a
then을 사용하는 경우 .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가 있음 에 유의):-U
U
ls
-U
ls -U | sort -o list
답변4
크레딧의 일부/대부분은 @StephenHarris에게 전달됩니다…
echo "`ls`" > list
동등하다
echo "$(ls)" > list