Jak dołączyć tekst na początku i na końcu wielu plików tekstowych w Bash?

24

Mam katalog pełen plików tekstowych. Moim celem jest dołączenie tekstu na początku i na końcu każdego z nich. Tekst na początku i na końcu jest taki sam dla każdego pliku.

W oparciu o kod, który dostałem z sieci, jest to kod dołączany na początku pliku:

echo -e 'var language = {\n$(cat $BASEDIR/Translations/Javascript/*.txt)' > $BASEDIR/Translations/Javascript/*.txt

Jest to kod dołączany na końcu pliku. Celem jest dodanie tekstu };na końcu każdego pliku:

echo "};" >> $BASEDIR/Translations/Javascript/*.txt

Przykłady, z których czerpałem, dotyczyły działania na poszczególnych plikach. Pomyślałem, że spróbuję działając na wielu plików przy użyciu symboli wieloznacznych, *.txt.

Mogę także popełniać inne błędy. W każdym razie, jak dołączyć tekst na początku i na końcu wielu plików?

Indagator
źródło

Odpowiedzi:

27

Aby dodać tekst do pliku, którego możesz użyć (z implementacją GNU sed):

sed -i '1i some string' file

Dołączanie tekstu jest tak proste, jak

echo 'Some other string' >> file

Ostatnią rzeczą do zrobienia jest umieszczenie tego w pętli, która iteruje wszystkie pliki, które zamierzasz edytować:

for file in *.txt; do
  sed -i '1i Some string' "$file" &&
  echo 'Some other string' >> "$file"
done
Marco
źródło
8

Możesz użyć GNU sed

Jak już pokazano, możesz wstawiać wiersze tekstu tuż przed i po dopasowaniu wierszy pliku za sedpomocą odpowiednio poleceń ii a. Nie pokazano, że można to zrobić za pomocą jednego linijki i dla wielu plików jednocześnie.

Poniższe wstawi linię przed pierwszą 1ii po ostatniej linii $a. Wstawienia zostaną wykonane dla wszystkich plików pasujących do globu *.txt.

sed -i -e '1ivar language = {' -e '$a};' -- *.txt

Oba ii adziałają nie tylko z numerami linii, ale także na każdej linii pasującej do danego wzorca. Spowodowałoby to wstawienie komentarza, ilekroć wiersz zawiera var y = 2;:

sed -i -- '/var y = 2;/i//initialize variable y' *.js
J. Katzwinkel
źródło
5

Komenda w pełni zgodna z POSIX, wykorzystująca ex:

for f in *.txt; do printf '%s\n' 0a 'var language = {' . '$a' '};' . x | ex "$f"; done

Jeśli uruchomisz printfczęść polecenia samodzielnie, zobaczysz dokładne polecenia edycji, które przekazuje ex:

0a
var language = {
.
$a
};
.
x

0aoznacza „Dołącz tekst po wierszu 0” (innymi słowy, przed pierwszym wierszem). Kolejny wiersz to dosłowny tekst, który „dołącza” po wierszu 0. Kropka ( .) w wierszu sama w sobie kończy tekst, który ma zostać dołączony.

$a oznacza dołączenie tekstu po ostatnim wierszu pliku.

x oznacza, aby zapisać zmiany i wyjść.

Dzika karta
źródło
2

Oto sposób na zrobienie tego w Perlu:

for f in ./*txt; do
  perl -lpe 'BEGIN{print "First string"}END{print "Last string"}' "$f" > foo && 
  mv foo "$f";
done
terdon
źródło
@ Dodawanie StéphaneChazelas -izamiast tego zastępowania pliku nie działa, po prostu drukuje na standardowe wyjście.
Oleh Prypin
@OlehPrypin, rzeczywiście masz rację. Komentarz usunięty.
Stéphane Chazelas
1

Spróbuj użyć ex:

ex -s +'bufdo!1s/^/HEAD/|$s/$/TAIL/' -cxa *.foo

gdzie są polecenia:

  • bufdo!wykonuje poniższe polecenia dla każdego otwartego bufora / pliku (uwaga: to nie jest POSIX )
  • 1s/^/HEAD/- wstawia HEADtekst do pierwszego wiersza na początku wiersza
  • $s/$/TAIL/- dołącza TAILtekst w ostatnim wierszu na końcu wiersza

a argumentami są:

  • -s - tryb cichy / szybki
  • -cxa - zapisz wszystkie otwarte bufory / pliki i wyjdź
  • *.foo- wszystkie pliki w bieżącym katalogu ( *) z foorozszerzeniem, wykorzystania **/*.foodla recursivity (po włączeniu globstar: shopt -s globstar)
kenorb
źródło
1
uwaga bufdo nie jest POSIX pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html
Steven Penny
1
@StevenPenny ma rację. Osobiście korzystam tylko z funkcji określonych w POSIX do edycji skryptowej.
Wildcard
1

Za gnu awkpomocą inplacerozszerzenia i BEGINFILE/ ENDFILE:

gawk -i inplace 'BEGINFILE{print "INSERT"};ENDFILE{print "APPEND"};1' ./*.txt
don_crissti
źródło
1

Ma również prawo być (z wynikami w .outplikach):

find . -name '*.txt' -exec sh -c '(echo HEAD;cat {};echo FOOT) > {}.out' \;

Kolejny, bardziej rozbudowany wariant - pliki źródłowe zastąpione wynikiem:

find . -name '*.txt' -exec sh -c '(echo HEAD;cat {};echo FOOT) > {}.tmp && mv {}.tmp {}' \; -print
wieża
źródło
0

Perl One-Liner na ratunek:

perl -i -pe'$_="FIRST LINE\n$_"if$.<2;$.=0,$_.="LAST LINE\n"if eof' *.txt
Kjetil S.
źródło