我在一个文件夹中有一个2000个文件的列表。我需要迭代10个文件,为每个文件执行一个shell命令(总共10个命令(,等待批处理完成,然后迭代接下来的10个文件直到没有文件为止。
理想情况下,我想删除/path/to/source_dir/中我已经迭代过的文件。我想不通。任何建议都会有帮助。
find /path/to/source_dir -type f -print0 | sed 's//path/to/source_dir///g' |xargs -0 -L10 sh -c '{ for i in $@; do /opt/dns_parse/1.1/bin/dns_parse -F avro -dc -e $SOURCE -i $SENSOR -B /path/to/dest_dir/$i /path/to/source_dir/"$i" & done; wait}'
您可以指示Bash使用mapfile -n 10
一次只读取10个条目。
以下是使用mapfile
:的特色脚本
#!/usr/bin/env bash
source_dir='/path/to/source_dir/'
find "$source_dir" -type f -print0 |
# Map a list of maximum ten files
while mapfile -d '' -n 10 files_per_ten && [ ${#files_per_ten[@]} -gt 0 ]; do
# Iterate indexes in the list
for source_file_path in "${files_per_ten[@]}"; do
# Strip the leading source_dir path out of the source_file_path
source_file="${source_file_path#$source_dir}"
# If executing the dns_parse command is successful
if /opt/dns_parse/1.1/bin/dns_parse
-F avro -dc -e "$SOURCE" -i "$SENSOR"
-B "/path/to/dest_dir/$source_file" "$source_file_path"
then
# Delete the source file
rm -f -- "$source_file_path"
fi & # Run the if-fi commands group as a background task
done
# Wait all background tasks
wait
done
所以一次读取10行。
find ..... -print0 |
while
files=()
for ((i=0; i<10; ++i)); do
if ! IFS= read -r -d '' tmp; then
break
fi
files+=("$tmp")
done
(( ${#files[@]} ))
do
# use "${files[@]}"
done
但tbh只需等待每10个文件。
find .... | {
num=0
while IFS= read -r -d '' file; then
stuff "$file" &
if ((num++ == 10)); then
wait
num=0
fi
done
}
如果您打算使用xargs
并使用bash,请不要使用xargs sh -c 'very long unreadable double-qouted stuff here'
。导出bash函数。
mywork() {
stuff here
readable
}
export -f mywork
find .... | xargs bash -c 'mywork "$@"' _
wait}'
将是一个语法错误——在}
之前必须有一个;
,就像wait; }'
一样。CCD_ 9将进行分词。记得用shellcheck检查你的脚本。-0 -L10
很奇怪,我会做-0 -n10
。
一次处理10个文件,等待批处理完成。在下面的脚本中,创建了30个sleep
脚本用于演示。
#!/bin/bash
source="$HOME/tmp/mp3"
# create 30 dummy sleep scripts
for i in {1..30}; do echo "sleep 5" > "file$i"; chmod 755 "file$i"; done
echo "$(find "${source}" -name 'file*' | wc -l) files to process"
i=0
c=0
while IFS= read -r -d $' ' file; do
while [ "$i" -eq 10 ] && jobs -l | tr 'n' ';' | grep -q 'Running' ; do
echo "waiting $(jobs -l | grep -c 'Running') processes"
# tune this value as needed
sleep 6
done
if [ "$i" -eq 10 ]; then
echo "10 files processed"
i=0
fi
if [ "$i" -lt 10 ]; then
echo "Processing $i"
##### process to wait for ####
source "$(basename "$file")" &
((i=i+1))
fi
((c=c+1))
done < <(find "${source}" -type f -print0)
echo "Total $c files processed"
rm "${source}"/file*
输出:
30 files to process
Processing 0
Processing 1
Processing 2
...
Processing 9
waiting 10 processes
10 files processed
Processing 0
Processing 1
...
Processing 9
waiting 10 processes
10 files processed
Processing 0
Processing 1
Processing 2
...
Processing 9
Total 30 files processed