디렉토리에 많은 텍스트 파일이 있으며 디렉토리에있는 모든 파일의 마지막 줄을 제거하고 싶습니다.
어떻게하니?
디렉토리에 많은 텍스트 파일이 있으며 디렉토리에있는 모든 파일의 마지막 줄을 제거하고 싶습니다.
어떻게하니?
답변:
GNU가 있다면이 멋진 oneliner를 사용할 수 있습니다 sed.
sed -i '$ d' ./*
현재 디렉토리에서 숨겨지지 않은 각 파일의 마지막 행을 제거합니다. -iGNU 스위치 sed는 제자리에서 작동하는 것을 의미 하고 마지막 줄 ( 마지막 의미 및 삭제 의미) 을 삭제하도록 '$ d'명령합니다 .sed$d
-i하고 있기 때문에 이것이 무의미하지만, 이전 버전의 일부 sed가 $와 d(또는, 일반적으로 패턴과 명령 사이).
*(.)하면 일반 파일 을 구할 수 있습니다 . 다른 쉘에 대해서는 알 수 없습니다.
디렉토리에 일반 파일 이외의 파일이 있거나 파일 이름에 공백 / 줄 바꿈이있는 파일이 있으면 다른 모든 답변에 문제가 있습니다. 다음은 관계없이 작동하는 것입니다.
find "$dir" -type f -exec sed -i '$d' '{}' '+'
find "$dir" -type f: 디렉토리에서 파일을 찾습니다 $dir
-type f 일반 파일입니다.-exec 찾은 각 파일에 대해 명령을 실행하십시오.sed -i: 파일을 제자리에 편집하십시오.'$d': d마지막 ( $) 행을 삭제 ( )합니다 .'+': find에 인수를 계속 추가하도록 지시합니다 sed(@zwol 덕분에 각 파일에 대해 개별적으로 명령을 실행하는 것보다 조금 더 효율적입니다).하위 디렉토리로 하강하지 않으려면에 인수 -maxdepth 1를 추가 할 수 있습니다 find.
find더 효율적으로 작성되었습니다 find $dir -type f -exec sed -i '$d' '{}' '+'.)
-print0전체 명령에 포함되어 있지 않은 이유는 무엇입니까?
-depth 0작동하지 않습니다 (findutils 4.4.2) 대신 대신해야합니다 -maxdepth 1.
-exec.
GNU를 사용 sed -i '$d'한다는 것은 전체 파일을 읽고 마지막 줄없이 사본을 만드는 것을 의미하지만 파일을 제자리에 잘리는 것이 훨씬 효율적입니다 (적어도 큰 파일의 경우).
GNU truncate를 사용하면 다음을 수행 할 수 있습니다.
for file in ./*; do
[ -f "$file" ] &&
length=$(tail -n 1 "$file" | wc -c) &&
[ "$length" -gt 0 ] &&
truncate -s "-$length" "$file"
done
파일이 상대적으로 작 으면 파일 당 여러 명령을 실행하기 때문에 효율성이 떨어질 수 있습니다.
마지막 줄 바꿈 문자 다음에 마지막 줄 다음에 여분의 바이트가 포함 된 파일 또는 다른 말로 , 구분되지 않은 마지막 줄 이 있으면 tail구현 에 따라 tail -n 1해당 여분의 바이트 (GNU와 같은 tail) 만 반환합니다 . 또는 마지막 (적절하게 구분 된) 줄과 여분의 바이트.
|wc -c에 tail전화? (또는 a ${#length})
${#length}바이트 $(...)가 아닌 문자 수를 계산 하고 테일링 줄 바꿈 문자를 제거하므로 ${#...}모든 문자가 1 바이트 일지라도 1 만큼 줄어 듭니다 .
보다 편리한 접근 방식 :
for f in ./*
do
test -f "$f" && ed -s "$f" <<\IN
d
w
q
IN
done
나는 이것이 설명이 필요하다고 생각하지 않습니다 ...이 경우에는 기본적으로 마지막 줄을 선택하기 때문에 d동일 하다는 것을 제외하고 .
재귀 적으로 검색하지 않으며 숨겨진 파일 (일명 도트 파일)을 처리하지 않습니다.
그것들을 편집하려면 디렉토리 안의 숨겨진 파일과 *를 일치시키는 방법을 참조하십시오$ded
[[]]하면 []POSIX와 완전히 호환됩니다. ( [[ ... ]]Bashism이다.)
[[비난은 아니지만 )
도트 파일을 포함하여 현재 디렉토리에서 재귀 적으로 시작하는 모든 파일에 대한 POSIX 호환 단일 라이너 :
find . -type f -exec sh -c 'for f; do printf "\$d\nx\n" | ex "$f"; done' sh {} +
를 들어 .txt파일 만이 아닌 재귀 :
find . -path '*/*/*' -prune -o -type f -name '*.txt' -exec sh -c 'for f; do printf "\$d\nx\n" | ex "$f"; done' sh {} +
참조 :