Bash에서 파일의 마지막 줄 제거


Answers

GNU sed 사용 :

sed -i '$ d' foo.txt

-i 옵션은 3.95 이전의 GNU sed 버전에는 존재하지 않으므로 임시 파일과 함께 필터로 사용해야합니다 :

cp foo.txt foo.txt.tmp
sed '$ d' foo.txt.tmp > foo.txt
rm -f foo.txt.tmp

물론,이 경우에 sed 대신 head -n -1 사용할 수도 있습니다.

Question

다음 줄을 포함하는 foo.txt 파일이 있습니다.

a
b
c

나는 foo.txt 의 내용을 얻는 간단한 명령을 원한다.

a
b



나는 거대한 파일 (~ 300Gb)로 작업 중이었기 때문에 모든 해결책에 문제가있었습니다. 내 솔루션은 다음과 같습니다.

dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc )

단어로 : 당신이 끝내고 싶은 파일의 길이를 알아 내고 (파일의 길이에서 마지막 줄의 길이의 길이, bc 사용하여), 그 위치를 파일의 끝으로 설정하십시오. /dev/null 을 그 위에 올려 놓습니다).

tail 가 끝에서부터 읽기 시작하고 dd 가 파일의 모든 행을 복사 (및 구문 분석)하기보다는 그 자리에 덮어 씁니다. 이는 다른 해결책이하는 것입니다.

참고 :이 위치에서 파일에서 선을 제거합니다! 자신의 파일에서 시도하기 전에 더미 파일을 백업하거나 테스트 해보십시오!




이 두 가지 솔루션은 다른 형태로 제공됩니다. 나는 이것들이 조금 더 실용적이고 명확하고 유용하다는 것을 발견했다.

dd 사용 :

BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
dd if=${ORIGINALFILE} of=${ORIGINALFILE}.tmp status=none bs=1 count=$(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc )
/bin/mv -f ${ORIGINALFILE}.tmp ${ORIGINALFILE}

truncate 사용 :

BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
truncate -s $(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc ) ${ORIGINALFILE}



루비 (1.9 이상)

ruby -ne 'BEGIN{prv=""};print prv ; prv=$_;' file



awk 'NR>1{print buf}{buf = $0}'

기본적으로이 코드는 다음과 같이 말합니다.

첫 번째 줄 이후의 각 줄에 대해 버퍼링 된 줄을 인쇄하십시오.

각 줄마다 버퍼를 재설정하십시오.

버퍼가 한 줄 씩 뒤떨어져 있으므로 1 행에서 n-1 행까지 인쇄됩니다.




awk "NR != `wc -l < text.file`" text.file |> text.file

이 스 니펫은 트릭을 수행합니다.




이것은 특히 가장 큰 파일에서 가장 빠르고 간단한 솔루션입니다 :

head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt

상위 행을 삭제하려면 다음을 사용하십시오.

tail -n +2 foo.txt

이는 라인 2에서 시작하는 출력 라인을 의미합니다.

파일의 상단이나 하단에서 줄을 지우는 데 sed 를 사용하지 마십시오. 파일이 클 경우에는 매우 느립니다.




echo -e '$d\nw\nq'| ed foo.txt



Mac 사용자

파일 자체를 변경하지 않고 마지막 줄만 삭제 된 출력 만 원한다면

sed -e '$ d' foo.txt

입력 파일 자체의 마지막 줄을 삭제하려면

sed -i '' -e '$ d' foo.txt




Mac 사용자 :

Mac에서는 head -n -1이 작동하지 않습니다. 그리고 "머리 처리"및 / 또는 "꼬리"명령을 사용하는 경우에만이 문제를 해결할 수있는 간단한 솔루션 (처리 시간 걱정없이)을 찾으려고했습니다.

나는 다음과 같은 일련의 명령을 시도해보고 "꼬리"명령 [Mac에서 사용할 수있는 옵션]을 사용하여 해결할 수있어서 기뻤습니다. 따라서 Mac을 사용하면서 "꼬리"만 사용하여이 문제를 해결하려면 다음 명령을 사용하십시오.

cat file.txt | 꼬리 -r | 꼬리 - n +2 | 꼬리 - r

설명 :

1> tail -r : 단순히 입력의 줄 순서를 뒤집습니다.

2> tail -n +2 : 두 번째 줄부터 시작하여 모든 줄을 출력한다.




전체 파일을 읽지 않거나 아무것도 다시 쓰지 않고 마지막 줄을 파일에서 제거하려면 다음을 사용할 수 있습니다.

tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}

마지막 줄을 제거하고 stdout ( "pop"it)에 인쇄하려면, 다음 명령을 tee 와 결합 할 수 있습니다.

tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{})

이 명령은 매우 큰 파일을 효율적으로 처리 할 수 ​​있습니다. 이것은 Yossi의 답과 비슷하지만, 몇 가지 추가 기능을 사용하지 않습니다.

이러한 작업을 반복적으로 사용하고 오류 처리 및 기타 기능을 원할 경우 여기에서 poptail 명령을 사용할 수 있습니다. https://github.com/donm/evenmoreutils