나는 수천 개의 .xyz
파일을 가지고 있는데, 모두 같은 디렉토리에 숫자 데이터가 있습니다. 그 중 일부는 끝에 "END"라는 텍스트 문자열이 있습니다. grep
원래 파일 이름 끝에 무언가를 추가하면서 "END"가 제거되고 새 파일이 생성되도록 명령을 반복하는 방법을 잘 모르겠습니다 .
내 파일 중 일부의 마지막 몇 줄 예
-1.10949170 55.68890280 -67.60000000
-0.92807500 55.64095280 -89.80000000
-0.95770560 55.66495830 -82.40000000
-0.90995000 55.63676110 -94.00000000
-1.03738890 55.65107220 -70.20000000
END
많은 파일에서 END를 제거하고 싶습니다.
-1.10949170 55.68890280 -67.60000000
-0.92807500 55.64095280 -89.80000000
-0.95770560 55.66495830 -82.40000000
-0.90995000 55.63676110 -94.00000000
-1.03738890 55.65107220 -70.20000000
원본 파일 이름: survey_2015_xxx.xyz
새 파일 이름: survey_2015_xxx_s.xyz
답변1
head
음수 오프셋을 지원하는 경우 :
for file in *.xyz; do
if [ "$(tail -n 1 < "$file")" = END ]; then
head -n -1 < "$file" > "${file%.xyz}_s.xyz"
fi
done
(그렇지 않은 경우 head -n -1
로 대체하십시오 sed '$d'
).
다음을 통해 효율성을 향상할 수 있습니다 ksh93
.
for file in *.xyz; do
if IFS= read -r last4 < "$file" <#((EOF-4)) <#((here=CUR)) &&
[ "$last4" = END ]; then
command /opt/ast/bin/head -c "$here" < "$file" > "${file/%.xyz/_s\0}"
fi
done
내장된 명령만 사용하기 때문입니다.
파일 시스템이 참조 링크 복사본을 지원하는 경우(즉, 수정될 때까지 데이터가 반복되지 않는 파일을 복사하여 시간과 디스크 공간을 절약하는 경우) ksh93
GNU를 계속 cp
사용할 수 있습니다.
for file in *.xyz; do
if IFS= read -r last4 < "$file" <#((EOF-4)) &&
[ "$last4" = END ]; then
newfile=${file/%.xyz/_s\0}
cp --reflink=auto -- "$file" "$newfile" &&
: 1<>; "$newfile" >#((EOF-4))
fi
done
즉, 우리는 reflink의 복사본을 만들고 끝에서 4바이트를 자릅니다.
답변2
또 다른 ed
옵션은 단 한 번만 살기 때문에 다음과 같습니다.
for f in *.xyz; do
printf '%s\n' ';g/END/d\' "w ${f%.xyz}_s.xyz" q | ed -s "$f"
done
파일 이름에 대한 참고 사항:
- 파일 이름은 로 시작하면 안 됩니다
!
. 그렇지 않으면ed
버퍼를 명령에 파이프하려고 시도합니다. ed
공백 문자는 명령을 경로 이름 인수와 구분하는 데 사용되므로 파일w
이름의 선행 공백은 유지되지 않습니다.- 줄바꿈이 포함된 파일 이름은 문제를 야기합니다.
ed
줄바꿈은 명령을 구분하는 데 사용되기 때문입니다.
정상적인 세상에서는 이러한 제한 사항 중 어느 것도 중요하지 않습니다. 잘……
답변3
그냥 다른 솔루션을 사용하세요sed
for file in *.xyz
do
if [ "$(sed -e '$!d' $file)" = END ]
then
sed -e '$d' $file > $file_s.xyz
fi
done