디렉토리에서 모든 파일의 마지막 줄을 제거하는 방법?


17

디렉토리에 많은 텍스트 파일이 있으며 디렉토리에있는 모든 파일의 마지막 줄을 제거하고 싶습니다.

어떻게하니?


6
무엇을 시도 했습니까? unix.stackexchange.com/help/how-to-ask : "연구를 공유하면 모든 사람을 도울 수 있습니다. 발견 한 내용과 요구 사항을 충족하지 못한 이유를 알려주십시오. 이는 귀하가 자신을 돕기 위해 시간을 보냈 음을 보여줍니다. , 그것은 명백한 답변을 되풀이하지 못하게 해주 며 무엇보다도보다 구체적이고 관련있는 답변을 얻는 데 도움이됩니다! "
Patrick

왜 사람의 생각은 실수에 / 등 것은 :) 굽실 거리다 유도의 아주 특별한 품질을 가지고 적용 않습니다
rackandboneman

답변:


4

에 액세스 vim할 수있는 경우 다음을 사용할 수 있습니다.

for file in ./*
do
  if [ -f "${file}" ]
  then
    vim -c '$d' -c "wq" "${file}"
  fi
done

16

GNU가 있다면이 멋진 oneliner를 사용할 수 있습니다 sed.

 sed -i '$ d' ./*

현재 디렉토리에서 숨겨지지 않은 각 파일의 마지막 행을 제거합니다. -iGNU 스위치 sed는 제자리에서 작동하는 것을 의미 하고 마지막 줄 ( 마지막 의미 및 삭제 의미) 을 삭제하도록 '$ d'명령합니다 .sed$d


3
폴더에 일반 파일 이외의 다른 파일 (예 : 다른 폴더)이 포함 된 경우 오류가 발생하고 아무 것도하지 않습니다.
Najib Idrissi

1
@StefanR 당신은 GNUism을 사용 -i하고 있기 때문에 이것이 무의미하지만, 이전 버전의 일부 sed$d(또는, 일반적으로 패턴과 명령 사이).
zwol

1
@zwol 내가 썼을 때, 이것은 경고가 아닌 오류 를 초래하며 , sed는 해당 파일에 도달하면 (최소한 sed 버전으로) 포기합니다. 다음 파일은 처리되지 않습니다. 오류 메시지를 버리는 것은 그것이 일어난 일조차 알지 못하기 때문에 끔찍한 생각입니다! zsh를 사용 *(.)하면 일반 파일 을 구할 수 있습니다 . 다른 쉘에 대해서는 알 수 없습니다.
Najib Idrissi

@NajibIdrissi 흠, 맞아. 놀랍습니다. 디렉토리에 대해 불평 할 것으로 예상했지만 명령 줄에서 다음 파일로 이동하십시오. 사실, 나는 그것을 버그로보고 할 것이라고 생각합니다.
zwol

@don_crissti 나는 GNU sed v4.3도 가지고 있습니다 ... 나는 당신에게 무엇을 말 해야할지 모르겠다. gist.github.com/nidrissi/66fad6be334234f5dbb41c539d84d61e
Najib Idrissi

11

디렉토리에 일반 파일 이외의 파일이 있거나 파일 이름에 공백 / 줄 바꿈이있는 파일이 있으면 다른 모든 답변에 문제가 있습니다. 다음은 관계없이 작동하는 것입니다.

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.


1
흠, 그러나 다른 답변과 달리 이것은 하위 디렉토리로 내려갑니다 . (또한, 현재 버전으로 find더 효율적으로 작성되었습니다 find $dir -type f -exec sed -i '$d' '{}' '+'.)
zwol

@zwol 감사합니다, 나는 그것을 대답에 추가했습니다.
Najib Idrissi

-print0전체 명령에 포함되어 있지 않은 이유는 무엇입니까?
Ruslan

1
또한 -depth 0작동하지 않습니다 (findutils 4.4.2) 대신 대신해야합니다 -maxdepth 1.
Ruslan

@Ruslan 나는 xargs를 사용한 첫 번째 버전을 가지고 있었지만 기억했다 -exec.
Najib Idrissi

9

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 -ctail전화? (또는 a ${#length})
Jeff Schaller

@JeffSchaller. 죄송합니다. 실제로 wc -c는 의도 된 것입니다. ${#length}바이트 $(...)가 아닌 문자 수를 계산 하고 테일링 줄 바꿈 문자를 제거하므로 ${#...}모든 문자가 1 바이트 일지라도 1 만큼 줄어 듭니다 .
Stéphane Chazelas

6

보다 편리한 접근 방식 :

for f in ./*
do
test -f "$f" && ed -s "$f" <<\IN
d
w
q
IN
done

나는 이것이 설명이 필요하다고 생각하지 않습니다 ...이 경우에는 기본적으로 마지막 줄을 선택하기 때문에 d동일 하다는 것을 제외하고 . 재귀 적으로 검색하지 않으며 숨겨진 파일 (일명 도트 파일)을 처리하지 않습니다. 그것들을 편집하려면 디렉토리 안의 숨겨진 파일과 *를 일치시키는 방법을 참조하십시오$ded


좋은! 로 변경 [[]]하면 []POSIX와 완전히 호환됩니다. ( [[ ... ]]Bashism이다.)
와일드

@Wildcard-감사합니다, 변경되었습니다 ( [[비난은 아니지만 )
don_crissti

비 POSIX주의라고 말해야합니다. :)
와일드 카드

3

도트 파일을 포함하여 현재 디렉토리에서 재귀 적으로 시작하는 모든 파일에 대한 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 {} +

참조 :

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.