파일의 마지막 50줄을 유지하고 매분마다 온도를 저장해 보았습니다. 나는 다음 명령을 사용했습니다.
tail -n 50 /home/pi/Documents/test > /home/pi/Documents/test
그러나 결과는 빈 테스트 파일입니다. 나는 그것이 테스트 파일의 마지막 50줄을 나열하고 그것을 테스트 파일에 삽입할 것이라고 상상합니다. 이 명령을 사용할 때:
tail -n 50 /home/pi/Documents/test > /home/pi/Documents/test2
잘 작동합니다. test2 파일에는 50줄이 있습니다.
누구든지 문제가 무엇인지 설명할 수 있습니까?
답변1
문제는 쉘이 명령을 실행하기 전에 명령 파이프라인을 설정한다는 것입니다. "입력 및 출력" 문제가 아니라 tail이 실행되기 전에 파일 내용이 사라지는 것입니다. 다음과 같이 진행됩니다.
- 쉘은
>
쓰기 위해 출력 파일을 열고 이를 자릅니다. - 쉘은 이 출력에 대해 파일 설명자 1(표준 출력용)을 설정합니다.
- 쉘 실행
tail
. tail
실행하고 열어보고/home/pi/Documents/test
아무것도 찾지 마세요.
많은 해결 방법이 있지만 핵심은 문제를 이해하고, 정확히 무엇이 잘못되고 있으며, 그 이유는 무엇인지 이해하는 것입니다.
그러면 당신이 찾고 있는 것이 나올 것입니다.
echo "$(tail -n 50 /home/pi/Documents/test)" > /home/pi/Documents/test
설명하다:
$()
명령 대체라고 알려진 실행tail -n 50 /home/pi/Documents/test
- 따옴표는 출력에서 개행을 유지합니다.
> /home/pi/Documents/test
출력을echo "$(tail -n 50 /home/pi/Documents/test)"
동일한 파일로 리디렉션합니다.
답변2
파일 리디렉션 파일을 먼저 지우는 또 다른 솔루션은 다음을 sponge
사용하는 것입니다.moreutils
다음과 같이 포장하세요.
tail -n 50 /home/pi/Documents/test | sponge /home/pi/Documents/test
답변3
이는 bash가 리디렉션을 먼저 처리하여 >
파일 내용을 삭제하기 때문입니다. 그런 다음 명령을 실행합니다. 를 사용하면 >>
마지막 50줄이 파일의 현재 내용 끝에 추가됩니다. 이 예에서는 동일한 50개 행이 두 번 반복됩니다.
다른 파일로 리디렉션되면 명령이 예상대로 작동합니다. 다음은 파일의 마지막 50줄을 동일한 이름의 파일에 쓰는 한 가지 방법입니다.
tail -50 /home/pi/Documents/test > /home/pi/Documents/test2 && mv /home/pi/Documents/test2 /home/pi/Documents/test
먼저 마지막 50줄을 임시 파일에 쓴 다음 이를 이동하여 mv
원본 파일을 대체합니다.
주석에서 지적했듯이 파일이 아직 열려 있으면 작동하지 않습니다. 파일을 이동하면 새 inode가 생성되고 소유권과 권한이 변경될 수도 있습니다. 임시 파일을 사용하여 이를 수행하는 더 좋은 방법은 다음과 같습니다.
tail -50 /home/pi/Documents/test > /home/pi/Documents/test2 ; cat /home/pi/Documents/test2 > /home/pi/Documents/test
임시 파일도 삭제할 수 있지만, 삭제될 때마다 해당 내용을 덮어씁니다.
답변4
이제 셸 리디렉션의 주요 문제를 이해했으므로 파일을 마지막 50줄로 자르는 또 다른 방법이 있습니다.
file=/path/to/the/file
n=$(( $(wc -l < "$file") - 50 ))
[[ $n -gt 0 ]] && sed -i 1,${n}d "$file"
이 어려운 작업은 -i
(GNU) sed의 "제자리에서 편집" 기능에 의해 수행됩니다. 이 기능은 임시 파일에 출력을 생성하여 뒤에서 작동합니다. 나머지 줄은 sed 작업의 수학을 설정합니다. 즉:
- 파일( )의 줄 수를 세고
wc
50을 뺍니다n
. - 양수 이면
n
sed 명령을 실행하여 라인 1부터 n까지 삭제합니다.