January 2026

S M T W T F S
    1 23
45 678910
11121314151617
18192021222324
25262728293031

Style Credit

Expand Cut Tags

No cut tags
Saturday, January 1st, 2022 07:15 pm
Чё-то туплю. Народ, кому-нить попадался пример скрипта на bash, который бы рекурсивно обходил директории, обрабатывал находящиеся там файлы, при этом результат обработки файлов сохранял бы в другой директории с сохранением структуры исходных каталогов? Это актуально, например, при массовом перекодировании медиа.
Saturday, January 1st, 2022 05:59 pm (UTC)
find . -name "*.*" -exec PROGRAM VAR1 > ./newdir/{}

?

Не пробовал.
Saturday, January 1st, 2022 07:33 pm (UTC)
#!/bin/bash
# Программа вызывается с 2-мя аргументами
# PROGRAM in-file out-file

IN_DIR=$1/
OUT_DIR=$2/
PROGRAM=$3

# создаём структуру каталогов
for d in `find "$IN_DIR" -type d`; do
mkdir -p `echo $d | sed s%"$IN_DIR"%"$OUT_DIR"%`
done

for i in `find $IN_DIR -type f`; do
echo $i
$PROGRAM $i `echo $i | sed s%"$IN_DIR"%"$OUT_DIR"%`
done
Sunday, January 2nd, 2022 10:46 am (UTC)
Если структура большая, обломается - результат find не поместится в аргументы.
Тут надо делать наоборот - перенаправлять find на xargs. А уже оттуда - запускать скрипт, который работает со своими аргументами.

find $IN_DIR -type d -print0 | xargs -0 do_something.sh "$PROGRAM" "$IN_DIR" "$OUT_DIR"

do_something аналогична вашему скрипту, только работает на аргументах.
Monday, January 3rd, 2022 10:29 pm (UTC)
Ну да, что-то такое. Если у вас слишком много каталогов и файлов, то вместо for можно использовать

while read file
do
< тело цикла из for >
done < $(find $1 -type f -iname '*.mp4' -printf "%p\n")

Что-то вроде этого.

Мой вариант сперва ищет каталоги, потом создаёт их, а затем пробегает по файлам, избегая повторных mkdir -p, но это очень быстрая команда. Короче, ваш вариант ничуть не хуже моего. И он 100% заточен под вашу задачу.

Я и был уверен, что он не вполне подходит к вашей задаче, т.к. создание полного Т.З. для таких скриптов занимает больше, чем время написания скрипта.

P.S.

sed s/// заменяет одну подстроку на другую. Самая удобная команда. Т.е.

echo "Привет котлет!" | sed s/Привет/Пока/

выдаст

"Пока котлет!"

Причём / можно заменить на любой другой символ. Типа sed s%a%b%
Monday, January 3rd, 2022 10:30 pm (UTC)
Лучше while read, чем xargs.
Monday, January 3rd, 2022 10:59 pm (UTC)
Там список файлов передается поточно, поэтому может быть хоть терабайтным. bash - очень хитрая штука, в ней потоки/конвейеры обрабатываются как в Хаскеле, лениво.

При этом, в отличие от xargs, вам не надо писать отдельный скрипт + интерпретатор bash, который иногда оказывается слишком жирным, запускается ровно один раз, а не на каждый файл.

А в for список файлов формируется заранее, поэтому может упереться в размер какого-то буфера. Но это должно быть очень много файлов, у вас вряд ли столько.

Но, в целом, такие скрипты делаются по месту, поэтому никто их не пишет "навсегда".
Edited 2022-01-03 11:02 pm (UTC)