Как добавить содержимое конкретного текстового файла в каждый текстовый файл в каталоге и его подкаталогах?

Мне не нравится загромождать файлы исходного кода комментариями о лицензировании / атрибуции, но иногда это требование. Поэтому, имея десятки файлов исходного кода (организованных в дереве подкаталогов), мне нужно добавить один и тот же многострочный комментарий к началу каждого из них.

Я подозреваю, что это очень простая задача, связанная со стандартными инструментами командной строки GNU / Linux, хотя я едва ли умею их серьезно использовать, поэтому прошу прощения и прошу вас о помощи.

Мне нужно заменить каждый theTargetFile.txt в ./*.txt (в том числе в подкаталогах рекурсивно) с чем-то вроде cat theCommonComment.txt theTargetFile.txt .

Я также предпочел бы исключать файлы, устанавливающие конкретную более конкретную маску, например, рассматривать все *.txt но оставлять *.DontTouch.txt неповрежденным.

Я думаю, что самая сложная часть того, что мне действительно нужно, – это заклинание с фантастическим find которое будет проходить через подкаталоги, включая файлы *.txt и исключать файлы *.DontTouch.txt .

6 Solutions collect form web for “Как добавить содержимое конкретного текстового файла в каждый текстовый файл в каталоге и его подкаталогах?”

Самый прямой способ, который я вижу, это сделать с GNU find , bash и утилитой sponge от moreutils :

 find dir/with/files -name '*.txt' ! -name '*.DontTouch.txt' -print0 | while IFS= read -rd '' file; do echo 'cat path/to/theCommonComment.txt "$file" | sponge "$file"' done 

В его нынешнем виде это будет просто печатать команды cat / sponge фактически ничего не делая. Как только вы убедитесь, что у вас есть то, что вы хотите, вы можете удалить эхо и одиночные кавычки, окружающие команду.

Без использования опции sponge или -print0 для поиска, которая может быть недоступна для всех систем:

 find dir/with/files -name '*.txt' ! -name '*.DontTouch.txt' -exec sh ' for file; do tempfile=$(mktemp) cat path/to/theCommonComment.txt "$file" >"$tempfile" mv "$tempfile" "$file" done ' sh {} + 

Нет простого способа остановить это, просто напечатайте, что он будет делать, поэтому будьте осторожны. Одна вещь, на которую следует обратить внимание – убедитесь, что ваш файл theCommonComment.txt не находится в каталоге, в котором вы выполняете рекурсивную операцию (или, по крайней мере, убедитесь, что он исключен из поиска), иначе вы получите два заголовки в некоторых файлах.

Обновить

Последняя мысль заключается в том, что вы можете проверить, добавлен ли заголовок в файл. Это может быть полезно, если вы добавляете новые файлы и должны снова запустить команду. Он также сталкивается с проблемой наличия файла theCommonComment.txt в пути поиска. Эти два решения станут:

 comment_file=path/to/theCommonComment.txt size=$(wc -c "$comment_file") find dir/with/files -name '*.txt' ! -name '*.DontTouch.txt' -print0 | while IFS= read -rd '' file; do if [ cmp -n "$size" $comment_file" "$file" ]; do echo 'cat "$comment_file" "$file" | sponge "$file"' fi done 
 export comment_file=path/to/theCommonComment.txt export size=$(wc -c "$comment_file") find dir/with/files -name '*.txt' ! -name '*.DontTouch.txt' -exec sh ' for file; do if [ cmp -n "$size" $comment_file" "$file" ]; do tempfile=$(mktemp) cat "$comment_file" "$file" >"$tempfile" mv "$tempfile" "$file" fi done ' sh {} + 

На GNU / что угодно, чтобы вставить _after_ первую строку:

 find -name '*.txt' ! -name '*thispattern*' ! -name '*thatpattern*' \ -exec sed -si '1r TheLicense.txt' '{}' + 

для вставки файла раньше, простейший несколько медленнее и немного kludgier:

 find -name '*.txt' ! -name '*thispattern*' ! -name '*thatpattern*' \ -exec sed -si '1{h;s,.*,cat TheLicense.txt,ep;g}' '{}' + 

С zsh :

 zmodload zsh/mapfile setopt extendedglob # best in ~/.zshrc for f (Dir/**/(^*DontTouch).txt(N.)) mapfile[$f]=$mapfile[theCommonComment.txt]$mapfile[$f] 

Я бы создал файл как dummy с содержимым, которое вы хотите заменить. Такой dummy файл будет выглядеть ниже.

 <?php /** * * Copyright (C) MyCompany, Ltd. - All Rights Reserved * Unauthorized copying of this file, via any medium is strictly prohibited * Proprietary and Confidential * * */ 

После этого я выполнил бы следующий скрипт.

 for f in ./*; do sed -i '/<?php/{ s/<?php//g r dummy }' $f done 

Я заменяю <?php пробелами и заменяю его содержимым из dummy файла.

Конечно, вы можете изменить приведенный выше код в соответствии с вашими требованиями.

Однако есть гораздо более сложный способ сделать это.

 for f in *; do echo "whatever" > tmpfile cat $f >> tmpfile mv tmpfile $f done 

Вышеприведенный ответ был взят отсюда . Вы в основном помещаете содержимое сначала в tmp-файл, а затем добавляете исходное содержимое в tmp-файл. Теперь, после этого, вы переименуете tmpfile обратно в исходное имя файла.

Это решение использует bash, find, tac и sed.

Скопируйте следующий скрипт в файл и сделайте исполняемый файл: chmod +x script

Затем используйте следующее:

 ./script <DIR> <HEADERFILE> 

где

 <DIR> The directory containing files ( or directory containing files..) <HEADERFILE> The file to add on top of each file 

Это сценарий:

 #!/bin/bash # inset a file content at the beginning of each matching files DIR=$1 HEADER_FILE=$2 #the matching files will be ignored IGNORE_FILE="*.DontTouch.txt" insertHeader(){ local targetfile=$1 local headerfile=$2 echo "$targetfile" while read line do # echo $line sed -i "$targetfile" -e "1i$line\ " done< <(tac "$headerfile") } export -f insertHeader find "$DIR" -type f -name "*.txt" ! -name "$IGNORE_FILE" -exec bash -c "insertHeader {} $HEADER_FILE" \; 

Это решение воспользуется командами find и xargs:

 find . -name "*.txt" -a ! -name "*.DontTouch.txt" -print | xargs -n 1 cat theCommonComment.txt 
  • Найти файлы tar.gz в папке старше 20 дней и удалить
  • Сценарий оболочки Crontabbed, не способный создавать / записывать в файл
  • Аудио-плейлист с открытым исходным кодом «Стандартный»
  • Невозможно повторно установить / вернуться к чтению только после обновления пакета.
  • Изменение действия Open Open Folder Folder Folder
  • Может ли grep использоваться для поиска файлов с некоторой строкой в ​​их именах?
  • Прокрутите по 384 парам и создайте 384 новых конкатенированных файла
  • Как отслеживать все самые последние изменения файлов в моей системе UNIX?
  • Почему следующий скрипт удаляет себя?
  • Как создать относительную символическую ссылку, совместимую с POSIX, в / bin / sh?
  • Копирование без перезаписи не работает
  • Interesting Posts

    самый быстрый способ сделать tar.gz из дерева каталогов?

    Как установить SHELL = / bin / bash глобально для cron

    Настроить кнопку питания на выключение на Debian / Mac Mini G4

    Устранение неполадок с системой systemd в системе Centos 7

    Клавиатура (в основном) не работает в Wine

    Все ли пакеты, включенные в файлы Debian DVD / CD или самые популярные?

    Как установить системные шрифты как noto?

    Связь между версией ядра и версией ОС

    «Завершение работы компьютера при завершении» во время этапа кодирования Avidemux?

    Как я могу использовать инструменты unix с кириллическим текстом?

    Можно ли использовать divert в качестве альтернативы ipfw fwd?

    Как смоделировать отключение питания для одного клиента NUT?

    / readonly при загрузке, но не понимаю, почему. как исследовать и исправлять?

    vte.sh не сохраняет мою директорию gnome-terminal на новой вкладке

    Как печатать (чашки, lpr, что угодно …) в оттенках серого в стиле _generic_?

    Linux и Unix - лучшая ОС в мире.