Bash - Найти файл и вставить текст в начало пустых и непустых файлов? - PullRequest
0 голосов
/ 01 мая 2020

Я очень новичок в bash командах. Может ли кто-нибудь помочь мне в этом вопросе?

Я должен найти все файлы .txt в текущем каталоге и добавить текст в начале этих файлов. Я написал ниже команду-

find . -name *.txt | xargs sed -i '1iadd text here'

Эта команда отлично работает для всех непустых файлов. Но это не работает для тех файлов, которые пусты. Я понял, что это потому, что команда sed не может найти 1-ую строку в пустых файлах и, следовательно, команда не выполняется. Есть ли другой способ добавить текст к пустым файлам?

Ответы [ 3 ]

1 голос
/ 01 мая 2020

Текстовый редактор ed Unix может сделать это.

for f in *.txt; do
  printf '%s\n' '0a' 'insert some text here' . w | ed -s "$f"
done
find . -type f -name '*.txt' -exec sh -c 'for f; do printf "%s\n" 0a "insert some text here" . w | ed -s "$f"; done' {} +
find . -type f -name '*.txt' -print0 | while IFS= read -rd '' file; do ed -s "$file" <<< $'0a\ninsert some text here\n.\nw\nq'; done

Можно сделать с помощью сценария ed.

cat script.ed

Out out

0a
insert some text here
.
w
q

Теперь a for loop

for f in *.txt; do ed -s "$f" < ./script.ed; done

Использование find.

find . -type f -name '*.txt' -exec sh -c 'ed -s "$1" < ./script.ed' sh {} \;

Комбинация обоих.

find . -type f -name '*.txt' -exec sh -c 'for f; do ed -s "$f" < ./script.ed; done' _ {} +
  • Первая строка 1 и действие i (что означает вставка) в вашем примере, что также верно для ed, что означает, что оно не будет работать и с ed, поскольку файл пустой и не содержит строк, но здесь я использую адрес как 0, а действие a, что означает append, работает.

  • * script.ed произвольное имя и ./ в ./script.ed означают текущий рабочий каталог, если ваш скрипт ed находится где-то еще, добавьте / измените его на абсолютный путь вашего ed скрипта.

  • Предупреждение: ed редактируйте файлы на месте, поэтому обязательно сделайте резервную копию того, что вы редактируете на всякий случай ...

1 голос
/ 01 мая 2020

Трудно улучшить коротких игроков. Иногда полезно подготовить типичный, не требующий пояснений фрагмент кода, менее компактный, с некоторыми допущениями (здесь: временный файл), но работающий в 100% случаев, например:

for file in `ls *.txt`; do awk 'BEGIN {print "add text here"}{print$0}' $file > tmp.tmp | mv tmp.tmp $file; done

или скорее (отредактировано):

for file in ./*.txt; do awk 'BEGIN {print "add text here"}{print$0}' "$file" > tmp.tmp | mv tmp.tmp "$file"; done

, а затем попытаться смешать решения.

РЕДАКТИРОВАТЬ:

Если вам нужно использовать find, xargs и sed, а также sed не работают должным образом с пустыми файлами, вы можете добавить в файл пустую строку, вставить текст, а затем удалить добавленную строку:

find . -type f -name '*.txt' | xargs -I "%" sh -c 'echo "" >> "%"; sed -i -e "1iadd text here" -e "$ d" "%"'
0 голосов
/ 03 мая 2020

Предварительно добавить на место с помощью ex:

ex -s '+0s/^/add text here/' '+:wq' my_file

От стандартного ввода к стандартному выводу:

ex -s '+0s/^/add text here/' '+%print' '+:wq' /dev/stdin

Обратите внимание, что это работает только с одним файлом, в отличие от sed.

Итак, для вашей ситуации:

$ ls
empty  not_empty
$ stat --format '%n: %s' *
empty: 0
not_empty: 6
$ cat empty 
$ cat not_empty 
a
b
c
$ find . -type f | xargs -I '{}' ex -s '+0s/^/add text here/' '+:wq' '{}'
$ cat empty 
add text here
$ cat not_empty 
add text herea
b
c

Обратите внимание, что -I используется, чтобы заставить xargs выполнять ex один раз для файла, а не пытаться агрегировать аргументы.

И для полноты, пример фильтра из stdin в stdout:

$ printf "%s\n" hello world | ex -s '+0s/^/add text here/' '+%print' '+:wq' /dev/stdin
add text herehello
world
$ cat /dev/null | ex -s '+0s/^/add text here/' '+%print' '+:wq' /dev/stdin
add text here
...