Jak wstawić tekst na początku pliku?

213

Do tej pory udało mi się znaleźć sposób dodania wiersza na początku pliku, ale nie jest to dokładnie to, czego chcę. Pokażę to na przykładzie

Zawartość pliku

some text at the beginning

Wynik

<added text> some text at the beginning

Jest podobnie, ale nie chcę tworzyć z nim żadnej nowej linii ...

Chciałbym to zrobić, sedjeśli to możliwe.

użytkownik219882
źródło
Coś tu działa dla Ciebie? stackoverflow.com/questions/54365/… - nie musisz używać sed.
wkl

Odpowiedzi:

314

sed może działać pod adresem:

$ sed -i '1s/^/<added text> /' file

Co to za magia, 1sktórą widzisz przy każdej odpowiedzi tutaj? Adresowanie linii! .

Chcesz dodać <added text>pierwsze 10 linii?

$ sed -i '1,10s/^/<added text> /' file

Lub możesz użyć Command Grouping:

$ { echo -n '<added text> '; cat file; } >file.new
$ mv file{.new,}
kev
źródło
67
Aby faktycznie wstawić nowy wiersz: sed -i '1s / ^ / <dodano tekst> \ n /' plik
jslatts
1
Dlaczego warto używać -i ?? O człowieku mówi, że to jest przyrostek. linux.die.net/man/1/sed
endrigoantonini
-i oznacza w miejscu, możesz dodać przyrostek do -i, aby wykonać kopię zamiast nadpisywać. -i.new utworzy nowy plik z rozszerzeniem .new, ale po prostu -i zmodyfikuje plik bezpośrednio.
Jay Kamat
3
Zauważ, że sed nie będzie działał na pustym pliku - nie można w ogóle zrobić sedu z wejściem o długości 0.
jthill
2
Wadą tego rozwiązania jest to, że nie dodaje tekstu, jeśli plik jest pusty.
DBedrenko
41

Jeśli chcesz dodać linię na początku pliku, musisz dodać \n na końcu ciągu w najlepszym rozwiązaniu powyżej.

Najlepszym rozwiązaniem będzie dodanie łańcucha, ale w przypadku łańcucha nie doda on linii na końcu pliku.

sed -i '1s/^/your text\n/' file
Ali Reza Ebadat
źródło
27

Jeśli plik ma tylko jedną linię, możesz użyć:

sed 's/^/insert this /' oldfile > newfile

Jeśli to więcej niż jedna linia. jeden z:

sed '1s/^/insert this /' oldfile > newfile
sed '1,1s/^/insert this /' oldfile > newfile

Dołączyłem ten drugi, abyś wiedział, jak robić zakresy linii. Oba te „zamieniają” znacznik linii początkowej na dotkniętych liniach tekstem, który chcesz wstawić. Możesz także (zakładając, że jesteś sedwystarczająco nowoczesny) korzystać z:

sed -i 'whatever command you choose' filename

zrobić edycję w miejscu.

paxdiablo
źródło
11

Możesz użyć cat -

printf '%s' "some text at the beginning" | cat - filename
Lex
źródło
6
Spowodowałoby to tylko wyświetlenie tekstu, a po nim zawartości pliku, ale w ogóle go nie modyfikuje.
Adaephon,
To dobre rozwiązanie, zastanawiam się, dlaczego nie uzyskało żadnych pozytywnych opinii. Oto mój dobry panie. Ponadto, dlaczego printf, a nie proste echo?
ychaouche
1
@ychaouche - prawdopodobnie dlatego, że nie ma przenośnego sposobu, aby zapobiec echododaniu nowego wiersza?
Toby Speight
Próbowałem przekierować to do pliku, dołączając > filedo polecenia, które spamowało mój terminal"some text at the beginning"
theonlygusti
2
printf '%s' "some text" | cat - filename > tmpfile && mv tmpfile filename
luca
10

Aby wstawić tylko nowy wiersz:

sed '1i\\'

źródło
8

Użyj podpowłoki:

echo "$(echo -n 'hello'; cat filename)" > filename
Nick Roz
źródło
5

Pamiętaj, że w systemie OS X sed -i <pattern> filenie powiedzie się. Jeśli jednak podasz rozszerzenie kopii zapasowej sed -i old <pattern> file, filezostanie ono zmodyfikowane w trakcie file.oldtworzenia. Następnie możesz usunąć file.oldw swoim skrypcie.

Curt Clifton
źródło
4
Lub plik sed -i ''. Następnie po prostu edytuje się w miejscu i nie tworzy kopii zapasowych.
Harv
Odkryłem, że macOS sed chce kropki do edycji bez tworzenia kopii zapasowej: sed -i. Plik <pattern>
Bryan
4

PROBLEM: oznacz plik na górze pliku podstawową nazwą katalogu nadrzędnego.

Tj. Dla

/mnt/Vancouver/Programming/file1

oznacz na górze za file1pomocą Programming.

ROZWIĄZANIE 1 - niepuste pliki:

bn=${PWD##*/}    ## bn: basename

sed -i '1s/^/'"$bn"'\n/' <file>

1s umieszcza tekst w pierwszym wierszu pliku.

ROZWIĄZANIE 2 - puste lub niepuste pliki:

Powyższe sedpolecenie kończy się niepowodzeniem w przypadku pustych plików. Oto rozwiązanie oparte na /superuser/246837/how-do-i-add-text-to-the-beginning-of-a-file-in-bash/246841#246841

printf "${PWD##*/}\n" | cat - <file> > temp && mv -f temp <file>

Zauważ, że -wymagane jest polecenie in cat (odczytuje standardowe dane wejściowe: man catwięcej informacji można znaleźć). Tutaj uważam, że należy pobrać dane wyjściowe instrukcji printf (do STDIN), a następnie cat i plik do temp ... Zobacz także wyjaśnienie na dole http://www.linfo.org/cat .html .

Dodałem również -fdomv polecenia, aby uniknąć prośby o potwierdzenie podczas zastępowania plików.

Aby ponownie przejrzeć katalog:

for file in *; do printf "${PWD##*/}\n" | cat - $file > temp && mv -f temp $file; done

Zauważ też, że spowoduje to przerwanie ścieżek ze spacjami; istnieją rozwiązania gdzie indziej (np. globbing plików lubfind . -type f ... rozwiązania typu) dla nich.

DODATEK: Re: mój ostatni komentarz, ten skrypt pozwoli ci powracać do katalogów ze spacjami w ścieżkach:

#!/bin/bash

## /programming/4638874/how-to-loop-through-a-directory-recursively-to-delete-files-with-certain-extensi

## To allow spaces in filenames,
##   at the top of the script include: IFS=$'\n'; set -f
##   at the end of the script include: unset IFS; set +f

IFS=$'\n'; set -f

# ----------------------------------------------------------------------------
# SET PATHS:

IN="/mnt/Vancouver/Programming/data/claws-test/corpus test/"

# /superuser/716001/how-can-i-get-files-with-numeric-names-using-ls-command

# FILES=$(find $IN -type f -regex ".*/[0-9]*")        ## recursive; numeric filenames only
FILES=$(find $IN -type f -regex ".*/[0-9 ]*")         ## recursive; numeric filenames only (may include spaces)

# echo '$FILES:'                                      ## single-quoted, (literally) prints: $FILES:
# echo "$FILES"                                       ## double-quoted, prints path/, filename (one per line)

# ----------------------------------------------------------------------------
# MAIN LOOP:

for f in $FILES
do

  # Tag top of file with basename of current dir:
  printf "[top] Tag: ${PWD##*/}\n\n" | cat - $f > temp && mv -f temp $f

  # Tag bottom of file with basename of current dir:
  printf "\n[bottom] Tag: ${PWD##*/}\n" >> $f
done

unset IFS; set +f
Victoria Stuart
źródło
3

Cześć ze zwrotem karetki:

sed -i '1s/^/your text\n/' file
xck
źródło
3

Aby dodać linię na początku pliku:

sed -i '1iText to add\'
solidsnack
źródło
Obejmuje to nowy wiersz, którego pytający wyraźnie nie chce.
Toby Speight
Dzięki, że dałeś mi dokładnie to, czego potrzebuję
FindOutIslamNow
3

Jest bardzo prosty sposób:

echo "your header" > headerFile.txt
cat yourFile >> headerFile.txt
Raphael Villas Boas
źródło
O ... przepraszam, teraz, kiedy zdałem sobie sprawę, że chciałeś dodać na początku, a nie nową linię.
Raphael Villas Boas
Ale ja chciałem nową linię. Dzięki za uproszczone podejście.
TheSatinKnight
3

Dla zabawy, oto rozwiązanie, w edktórym nie ma problemu z działaniem na pustym pliku. Możesz umieścić go w skrypcie powłoki, tak jak każdą inną odpowiedź na to pytanie.

ed Test <<EOF
a

.
0i
<added text>
.
1,+1 j
$ g/^$/d
wq
EOF

Powyższy skrypt dodaje tekst do wstawienia do pierwszego wiersza, a następnie łączy pierwszy i drugi wiersz. Aby uniknąć wychodzenia z edycji po błędzie z nieprawidłowym złączeniem, najpierw tworzy pusty wiersz na końcu pliku i usuwa go później, jeśli nadal istnieje.

Ograniczenia: Ten skrypt nie działa, jeśli<added text> jest dokładnie równy jednemu okresowi.

merlin2011
źródło
2

moje dwa centy:

sed  -i '1i /path/of/file.sh' filename

To zadziała, nawet jeśli łańcuch zawiera ukośnik do przodu "/"

vardhan
źródło
1
echo -n "text to insert " ;tac filename.txt| tac > newfilename.txt

Pierwszy tacprzesuwa plik do tyłu (ostatni wiersz jako pierwszy), więc „tekst do wstawienia” pojawia się na końcu. Drugi taczawija go ponownie, tak aby wstawiona linia była na początku, a oryginalny plik w oryginalnej kolejności.

paulp
źródło
1
Czy możesz wyjaśnić, w jaki sposób pomogłoby to Tomasowi rozwiązać problem?
John Odom
tac | tac - tak powstają
nieskalowalne sposoby
0

Kolejne rozwiązanie z aliasami. Dodaj do pliku init rc / env:

addtail () { find . -type f ! -path "./.git/*" -exec sh -c "echo $@ >> {}" \; }
addhead () { find . -type f ! -path "./.git/*" -exec sh -c  "sed -i '1s/^/$@\n/' {}" \; }

Stosowanie:

addtail "string to add at the beginning of file"
addtail "string to add at the end of file"
0x8BADF00D
źródło