Скрипт Bash: рекурсивно катит TXT файлы в папках - PullRequest
0 голосов
/ 09 января 2019

У меня есть каталог файлов со структурой, подобной приведенной ниже:

./DIR01/2019-01-01/Log.txt
./DIR01/2019-01-01/Log.txt.1
./DIR01/2019-01-02/Log.txt
./DIR01/2019-01-03/Log.txt
./DIR01/2019-01-03/Log.txt.1
...
./DIR02/2019-01-01/Log.txt
./DIR02/2019-01-01/Log.txt.1
...
./DIR03/2019-01-01/Log.txt

... и так далее. В каждом каталоге DIRxx есть несколько подкаталогов, названных по дате, которые сами имеют ряд файлов журналов, которые необходимо объединить. Количество объединяемых текстовых файлов варьируется, но теоретически может достигать 5. Я хотел бы видеть следующую команду, выполняемую для каждого набора файлов в датированных каталогах (обратите внимание, что файлы должны быть объединены в обратном порядке):

cd ./DIR01/2019-01-01/
cat Log.txt.4 Log.txt.3 Log.txt.2 Log.txt.1 Log.txt > ../../Log.txt_2019-01-01_DIR01.txt

(я понимаю, что приведенная выше команда выдаст ошибку, что определенные файлы не существуют, но cat все равно сделает то, что мне нужно) Помимо cd входа в каждый каталог и запуска вышеуказанной команды cat, как я могу записать это в сценарий оболочки Bash?

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Не такой всеобъемлющий, как другие, но быстрый и простой. Используйте find и sort свой вывод, как вам нравится (-zrn - это --zero-terminated --reverse --numeric-sort), затем выполните итерации по нему с read.

find . -type f -print0 |
sort -zrn |

while read -rd ''; do
    cat "$REPLY";
done >> log.txt
0 голосов
/ 10 января 2019

Если вы просто хотите объединить все файлы во всех подкаталогах, имя которых начинается с Log.txt, вы можете сделать что-то вроде этого:

for dir in DIR*/*; do 
    date=${dir##*/}; 
    dirname=${dir%%/*}; 
    cat $dir/Log.txt* > Log.txt_"${date}"_"${dirname}".txt; 
done

Если вам нужны файлы в обратном числовом порядке, от 5 до 1, а затем Log.txt, вы можете сделать это:

for dir in DIR*/*; do 
    date=${dir##*/}; 
    dirname=${dir%%/*}; 
    cat $dir/Log.txt.{5..1} $dir/Log.txt > Log.txt_"${date}"_"${dirname}".txt; 
done

Это, как вы упомянули в своем вопросе, будет жаловаться на файлы, которые не существуют, но это всего лишь предупреждение. Если вы не хотите этого видеть, вы можете перенаправить вывод ошибок (хотя это также может привести к тому, что вы пропустите допустимые сообщения об ошибках):

for dir in DIR*/*; do 
    date=${dir##*/}; 
    dirname=${dir%%/*}; 
    cat $dir/Log.txt.{5..1} $dir/Log.txt > Log.txt_"${date}"_"${dirname}".txt; 
done 2>/dev/null
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...