How can I safely run directory updates in parallel with a job limit?

0
3
Asked By VelvetKite42 On

I have a Bash script that finds directories matching a condition, enters each directory, and runs update-this-dir.sh --file ./name.txt. There may be several thousand directories, and running the update sequentially takes a long time. What is a good way to process them concurrently while limiting the number of active jobs—for example, keeping 10 running at once or dividing the directories into batches? The solution should handle paths safely, avoid competing changes to the parent shell's working directory, and ideally preserve useful output and exit statuses.

3 Answers

Answered By SilverPanda56 On

If you want to stay in Bash, launch each directory operation in a subshell so every job has its own working directory, and keep a PID queue. A basic pattern is: max_jobs=10; pids=(); while IFS= read -r -d '' dir; do (( ${#pids[@]} >= max_jobs )) && { wait "${pids[0]}"; pids=("${pids[@]:1}"); }; ( cd "$dir" && printf 'nn%sn' "$PWD" && update-this-dir.sh --file ./name.txt ) & pids+=("$!"); done < <(find . -type d -iname '.config' -exec dirname {} ; -print0); wait "${pids[@]}". For larger jobs, a tool such as GNU parallel or xargs is generally simpler and gives better control over output and failures.

Answered By CopperLynx18 On

You can do this with xargs as well. Make update-this-dir.sh change into the supplied directory itself, then use: find . -type d -iname .config -exec dirname {} ; -print0 | xargs -0 -n1 -P10 -t update-this-dir.sh --dirpath. The -P10 keeps up to ten processes active; when one finishes, xargs starts another. Using null-delimited paths avoids problems with spaces and other special characters in directory names.

QuietBadger63 -

Be careful with the input redirection: use < list_of_dir when list_of_dir is a file, or pipe a command into xargs. Also use -print0 and -0 if paths may contain whitespace or newlines.

Answered By MangoOrbit7 On

GNU parallel is designed for exactly this. Have the update script accept the directory as an argument instead of relying on the caller's current directory, then run a fixed number of jobs at once. For example: find . -type d -iname .config -exec dirname {} ; -print0 | parallel -0 -j 10 --halt soon,fail=1 update-this-dir.sh --dirpath {}. The -j 10 setting limits concurrency, and GNU parallel also provides options for grouping or labeling output.

Related Questions

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.