Bash에서 파일 시작 부분에 텍스트를 어떻게 추가합니까?


285

안녕하세요, 텍스트를 파일 앞에 추가하고 싶습니다. 예를 들어 todo.txt 파일의 시작 부분에 작업을 추가하고 싶습니다. 나는 알고 echo 'task goes here' >> todo.txt있지만 파일 끝에 줄을 추가합니다 (원하는 것이 아님).


2
더 효율적인 방법이 할 수 없습니다 경우 그 큰 파일 : unix.stackexchange.com/questions/87772/...
치로 틸리新疆改造中心法轮功六四事件

@이 방법을 살펴볼 수 있습니까? superuser.com/a/1352628/11116
Evan Carroll

답변:


374
echo 'task goes here' | cat - todo.txt > temp && mv temp todo.txt

또는

sed -i '1s/^/task goes here\n/' todo.txt

또는

sed -i '1itask goes here' todo.txt

4
첫 번째는 훌륭하게 작동합니다! 논리를 설명해 주시겠습니까? 구문을 해석하는 방법을 특히 잘 모르겠습니다.
user479534

44
@ user8347 : (표준 입력)을 첫 번째 파일 로 사용하고 두 번째 파일로 사용 |하는 메시지 ( echo '...')를 파이프 ( )합니다 . 여러 파일을 연결합니다. 출력 ( )을이라는 파일로 보냅니다 . 오류 (있는 경우 )에서 다음이 (이름을 변경하지 )에 원본 파일로 다시 파일을 ( ). cat-todo.txtcat>temp&&catmvtemptodo.txt
Dennis Williamson

1
@itaifrenkel : 당신이 한 일을 봐야하지만 cat리터럴 백 슬래시 n을 받으면 줄 바꿈으로 변환하지 않습니다. 다른 일이 있었을 것입니다. 대신 백 슬래시와 n을 전송하는지 또는 개행인지 확인하기 cat위해 파이핑을 시도 hexdump -C하십시오. cat -e줄 끝을 표시 하려고 할 수도 있습니다 .
Dennis Williamson

1
2와 3을 사용하면 (3이 더 간단 해 보입니다) 텍스트를 여러 파일에 한 번 에 추가 할 수 있습니다 .
Felix

4
@ 키라 : 1수단은 파일의 한 줄에서만 다음 명령을 수행하며 i명령은 삽입입니다. 매뉴얼 페이지에서 "주소"섹션과 "제로 또는 단일 주소 명령"섹션을보십시오.
Dennis Williamson

73

내 의견으로는 더 간단한 옵션은 다음과 같습니다.

echo -e "task goes here\n$(cat todo.txt)" > todo.txt

내부 명령 이 덮어 쓰기 $(...)전에 실행되기 때문에 작동합니다.todo.txt> todo.txt

다른 답변은 잘 작동하지만 매일 에코와 고양이를 사용하기 때문에 기억하기가 훨씬 쉽습니다.

편집 : 플래그에 에코 todo.txt덕분에 백 슬래시가 있으면 -e해석 할 수 있으므로이 솔루션은 매우 나쁜 아이디어 입니다. 서문 문자열에 줄 바꿈을 넣는 훨씬 쉬운 방법은 다음과 같습니다.

echo "task goes here
$(cat todo.txt)" > todo.txt

... 줄 바꿈을 사용하기 만하면됩니다. 물론, 그것은 더 이상 하나의 라이너가 아니지만 현실적으로 이전의 하나의 라이너가 아니 었습니다. 스크립트 내 에서이 작업을 수행하고 들여 쓰기가 걱정되는 경우 (예 : 함수 내에서 이것을 실행하는 경우) 다음을 포함하여 이것에 잘 맞도록 몇 가지 해결 방법이 있습니다.

(echo 'task goes here' && cat todo.txt) > todo.txt
echo 'task goes here'$'\n'"$(cat todo.txt)" > todo.txt

또한 개행이 끝에 추가되는지 여부에 관심이있는 경우 todo.txt이를 사용하지 마십시오. 두 번째부터 마지막까지는 빼고 그것은 끝을 어지럽히 지 않습니다.


1
나는 $ (...)를 전혀 얻지 못한다.
SCL

2
그것은 작은 따옴표 대신 큰 따옴표로 더 잘 (또는 전혀) 작동 할 수 있습니다…
ℝaphink

5
-etodo.txt 내부에서도 이스케이프 시퀀스를 변환 하지 않습니까?
mk12

2
해결 방법은 다음과 같습니다-> cat : <대상 파일 이름> : 입력 파일이 출력 파일입니다.
ingyhere

printf는 플랫폼에서 훨씬 더 일관성이 있고 일반적으로 echo -e보다 더 매끄럽게 작동해야합니다.
Peter Berg

28

moreutils라는 좋은 도구가 sponge:

echo "task goes here" | cat - todo.txt | sponge todo.txt

STDIN을 "잠그고"파일에 쓰므로 임시 파일에 대해 걱정할 필요가 없습니다.

당신은 얻을 수 있습니다 moreutils통해, 많은 리눅스 배포판으로 apt-get install moreutils사용하거나 OS X에 브루을 함께 brew install moreutils.


나는 갈 것이다 (echo 'ble'; cat todo.txt):-)
치로 틸리가新疆改造中心法轮功六四事件

11

Ex 모드에서 Vim을 사용할 수 있습니다 :

ex -s -c '1i|task goes here' -c x todo.txt
  1. 1 첫 줄을 선택하십시오

  2. i 끼워 넣다

  3. x 저장하고 닫습니다


5

새로운 임시 파일을 만들 수 있습니다.

echo "new task" > new_todo.txt
cat todo.txt >> new_todo.txt
rm todo.txt
mv new_todo.txt todo.txt

당신은 또한 사용할 수 있습니다 sed또는 awk. 그러나 기본적으로 같은 일이 발생합니다.


1
디스크 공간이 부족하여 new_todo.txt부분적으로 만 쓰여집니다. 솔루션이 원본 파일을 잃어버린 것 같습니다.
NPE

누가 디스크 공간이 부족합니까? ;-) 간단한 예일뿐입니다.
Keith

2
@Keith 특히 큰 가상 드라이브가 필요하지 않은 VM에서 작업하는 사람. 또는 누군가 큰 파일을 옮기고 있습니다. 어쨌든 이것에 대한 실제 주장은 디렉토리 권한입니다. 주어진 디렉토리에 새로운 파일을 생성 할 권한이 없다면, 스크립트에서 성공적으로 실행되는 유일한 명령 rm은 원본 파일의 명령입니다.
Parthian Shot

3

텍스트 파일이 메모리에 들어가기에 충분히 작은 경우,이를 대체하기 위해 임시 파일을 만들 필요가 없습니다. 모두 메모리에로드하고 파일에 다시 쓸 수 있습니다.

echo "$(echo 'task goes here' | cat - todo.txt)" > todo.txt

전체 파일을 덮어 쓰지 않고 파일 시작 부분에 줄을 추가하는 것은 불가능합니다.


명백한 질문을하기 위해 : 쉘 변수의 문자 제한은 어디에 있습니까?
nixda

내가 아는 한, 사용 가능한 메모리 양에 의해서만 제한됩니다. 메모리에 100MB가 넘는 변수를 채워 넣었습니다. text=$(cat file). 쉘 변수가없는 바이너리 깨끗하고 있기 때문에,하지만에만 사용 텍스트에주의 mywiki.wooledge.org/BashFAQ/058
Rucent88

2

파일 시작 부분에 내용을 삽입 할 수 없습니다. 수행 할 수있는 유일한 작업은 기존 내용을 바꾸거나 파일의 현재 끝 뒤에 바이트를 추가하는 것입니다.

귀하의 질문에 대한 해결책은 임시 파일 (또는 버퍼)이 (메모리 또는 디스크에) 생성되어 결국 원본 파일을 덮어 쓸 것을 요구합니다.

프로세스 중에 파일 시스템이 가득 차면 새 파일을 작성하는 동안 원본 파일을 보존하여 데이터를 유실하지 않도록주의하십시오. 예 :

cat <(echo task go there) todo.txt > todo.txt.new && mv todo.txt.new todo.txt

Downvoter는 그들의 동기를 설명 할 수 있습니다. 수락 된 답변을 포함하여 나머지 답변 중 어느 것도 내 답변에 모순되지 않습니다.
jlliagre

<...> 괄호처럼 보이기 때문에 구문 분석하기가 어렵습니다. <와 (사이에 공백이 도움이 될까요?
dumbledad

이것은 나를 위해 작동하지 않습니다. echo HOME=\"/g/Users/timregan/\" | cat - 'F:\Program Files\Git\etc\profile'작동하지만 cat <echo HOME=\"/g/Users/timregan/\" 'F:\Program Files\Git\etc\profile'오류 : "에코 : 해당 파일 또는 디렉토리 없음"
dumbledad

@dumbledad 답장을 너무 많이 생각하고 있습니다. 당신이 그것을 파싱 할 것은 없습니다. <와 사이에 공백 (이 있으면 구문이 깨집니다. 시도cat <(echo HOME=\"/g/Users/timregan/\") 'F:\Program Files\Git\etc\profile'
jlliagre


0

GitBash + Windows10 + Multline :

다음은 여러 줄 문자열 을 사용할 수있는 버전입니다 .

##############################################
## This section for demo purpose only,      ##
## So you can save entire file as           ##
## whatever.sh and run it.                  ##
##                                          ##
##############################################
> MY_TARGET_FILE.txt ##Make Or Clear File
echo "[STARTER_CONTENT]" >> MY_TARGET_FILE.txt
##############################################

## Below is main code:

##################################################
TARGET_FILE_VARIABLE="MY_TARGET_FILE.txt"
ADD_TO_HEAD_VARIABLE=$(cat << "HEREDOC_HEAD_TEXT"
//|  +-------------------------------------+   |//
//|  |                                     |   |//
//|  |     MESSAGE_FOR_HEAD_OF_FILE        |   |//
//|  |                                     |   |//
//|  +-------------------------------------+   |//
HEREDOC_HEAD_TEXT
)
##################################################
TAR=$TARGET_FILE_VARIABLE                       ##
TEX=$ADD_TO_HEAD_VARIABLE                       ##
echo "$TEX" | cat - $TAR > TEMP && mv TEMP $TAR ##
##################################################

## Expected contents of MY_TARGET_FILE.txt :
## //|  +-------------------------------------+   |//
## //|  |                                     |   |//
## //|  |     MESSAGE_FOR_HEAD_OF_FILE        |   |//
## //|  |                                     |   |//
## //|  +-------------------------------------+   |//
## [STARTER_CONTENT]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.