如何添加计数器以查找 xargs
How to add counter to find xargs
所以我有这段代码,每个脚本可以生成 5 个文件。但是,我需要一个计数器
find cobacoba -type f | xargs -n 5 bash -c 'script.sh $counter [=10=] ' bash
Script.sh:
#!/usr/bin/env bash
echo "Group [=11=]: "
##This is just a simple example. The actual script will use each variable, including the counter, for further processing.
##So, really need all the variables being passed by "find | xargs"
希望结果:
Group 1: cobacoba/1.3 cobacoba/1.6 cobacoba/1.q cobacoba/1.5
Group 2: cobacoba/1.1 cobacoba/1.q2 cobacoba/1.q23 cobacoba/1.4
Group 3: cobacoba/1.2
我可以使用什么策略来创建 $counter ?
由于 |
管道的右侧是一个子 shell,它不能保留或更新变量。不可能像您那样在变量中使用计数器。
幸运的是 Bash 允许您反转操作并在子 shell 中使用命令 运行 的输出提供主 shell(这里是 while
循环) -shell。
由于我们在主 shell 中更新变量,它的工作方式如下:
#!/usr/bin/env bash
group=1 # Group counter
files_per_group=4 # How many files per group
filescount=0 # Files counter
newline='' # Newline code used between groups
# loop reading all null delimited files names returned by find -print0
while read -d '' -r file; do
# If count of file is a multiple of files per group, then start a new group
if [ $((filescount % files_per_group)) -eq 0 ]; then
printf '%sGroup %d:' "$newline" "$group"
# Increment group counter for upcoming group
group=$((group + 1))
newline=$'\n' # To separate next group in another line
fi
# Print space delimited file-name
printf ' %s' "$file"
# Increment the files counter
filescount=$((filescount + 1))
done < <(
# feed the whole while loop with the output of find
find cobacoba -type f -print0
)
echo
使用构建参数调用 bash 脚本的解决方案:
#!/usr/bin/env bash
# Dummy bashscript as a function to test call with parameters
bashscript() {
printf 'Called bashscript.sh\n'
printf 'group %s\n' ""
shift
printf '%d files:\n' "$#"
printf ' %s' "$@"
printf $'\n\n'
}
group=1 # Group counter
files_per_group=5 # How many files per group
filescount=0 # Files counter
bashscriptparams=() # Arguments for the bash scripts
# loop reading all null delimited files names returned by find -print0
while read -d '' -r file; do
# If count of file is a multiple of files per group, then start a new group
if [ $((filescount % files_per_group)) -eq 0 ]; then
#printf '%sGroup %d:' "$newline" "$group"
# Set the group number as first param of the bash script
bashscriptparams=("$group")
# Increment group counter for upcoming group
((group++))
fi
# Add the file as next parameter of the bash script
bashscriptparams+=("$file")
# Print space delimited file-name
#printf ' %s' "$file"
# If last file of group, then group is complete
if [ $((filescount % files_per_group)) -eq $((files_per_group - 1)) ]; then
# Launch the bash script with its arguments (group file_1 .. file_n)
bashscript "${bashscriptparams[@]}"
fi
# Increment the files counter
((filescount++))
done < <(
# feed the whole while loop with the output of find
find cobacoba -type f -print0
)
# If we reach here with an incomplete files group
if [ $((filescount % files_per_group)) -le $((files_per_group - 1)) ]; then
# Launch the bash script with its incomplete files arguments (group file_1 .. file_n)
bashscript "${bashscriptparams[@]}"
fi
输出:
Called bashscript.sh
group 1
5 files:
cobacoba/1.q2 cobacoba/1.3 cobacoba/1.1 cobacoba/1.5 cobacoba/1.6
Called bashscript.sh
group 2
4 files:
cobacoba/1.2 cobacoba/1.4 cobacoba/1.q cobacoba/1.q23
如果您只想递归遍历目录,则无需使用 find
或 xargs
:
i=0
shopt -s globstar
for f in cobacoba/**; do
[[ -f $f ]] || continue
(( i > 5 )) && wait
script.sh "$i" "[=10=]" "" "" "" "" "$f" &
(( i++ ))
done
所以我有这段代码,每个脚本可以生成 5 个文件。但是,我需要一个计数器
find cobacoba -type f | xargs -n 5 bash -c 'script.sh $counter [=10=] ' bash
Script.sh:
#!/usr/bin/env bash
echo "Group [=11=]: "
##This is just a simple example. The actual script will use each variable, including the counter, for further processing.
##So, really need all the variables being passed by "find | xargs"
希望结果:
Group 1: cobacoba/1.3 cobacoba/1.6 cobacoba/1.q cobacoba/1.5
Group 2: cobacoba/1.1 cobacoba/1.q2 cobacoba/1.q23 cobacoba/1.4
Group 3: cobacoba/1.2
我可以使用什么策略来创建 $counter ?
由于 |
管道的右侧是一个子 shell,它不能保留或更新变量。不可能像您那样在变量中使用计数器。
幸运的是 Bash 允许您反转操作并在子 shell 中使用命令 运行 的输出提供主 shell(这里是 while
循环) -shell。
由于我们在主 shell 中更新变量,它的工作方式如下:
#!/usr/bin/env bash
group=1 # Group counter
files_per_group=4 # How many files per group
filescount=0 # Files counter
newline='' # Newline code used between groups
# loop reading all null delimited files names returned by find -print0
while read -d '' -r file; do
# If count of file is a multiple of files per group, then start a new group
if [ $((filescount % files_per_group)) -eq 0 ]; then
printf '%sGroup %d:' "$newline" "$group"
# Increment group counter for upcoming group
group=$((group + 1))
newline=$'\n' # To separate next group in another line
fi
# Print space delimited file-name
printf ' %s' "$file"
# Increment the files counter
filescount=$((filescount + 1))
done < <(
# feed the whole while loop with the output of find
find cobacoba -type f -print0
)
echo
使用构建参数调用 bash 脚本的解决方案:
#!/usr/bin/env bash
# Dummy bashscript as a function to test call with parameters
bashscript() {
printf 'Called bashscript.sh\n'
printf 'group %s\n' ""
shift
printf '%d files:\n' "$#"
printf ' %s' "$@"
printf $'\n\n'
}
group=1 # Group counter
files_per_group=5 # How many files per group
filescount=0 # Files counter
bashscriptparams=() # Arguments for the bash scripts
# loop reading all null delimited files names returned by find -print0
while read -d '' -r file; do
# If count of file is a multiple of files per group, then start a new group
if [ $((filescount % files_per_group)) -eq 0 ]; then
#printf '%sGroup %d:' "$newline" "$group"
# Set the group number as first param of the bash script
bashscriptparams=("$group")
# Increment group counter for upcoming group
((group++))
fi
# Add the file as next parameter of the bash script
bashscriptparams+=("$file")
# Print space delimited file-name
#printf ' %s' "$file"
# If last file of group, then group is complete
if [ $((filescount % files_per_group)) -eq $((files_per_group - 1)) ]; then
# Launch the bash script with its arguments (group file_1 .. file_n)
bashscript "${bashscriptparams[@]}"
fi
# Increment the files counter
((filescount++))
done < <(
# feed the whole while loop with the output of find
find cobacoba -type f -print0
)
# If we reach here with an incomplete files group
if [ $((filescount % files_per_group)) -le $((files_per_group - 1)) ]; then
# Launch the bash script with its incomplete files arguments (group file_1 .. file_n)
bashscript "${bashscriptparams[@]}"
fi
输出:
Called bashscript.sh
group 1
5 files:
cobacoba/1.q2 cobacoba/1.3 cobacoba/1.1 cobacoba/1.5 cobacoba/1.6
Called bashscript.sh
group 2
4 files:
cobacoba/1.2 cobacoba/1.4 cobacoba/1.q cobacoba/1.q23
如果您只想递归遍历目录,则无需使用 find
或 xargs
:
i=0
shopt -s globstar
for f in cobacoba/**; do
[[ -f $f ]] || continue
(( i > 5 )) && wait
script.sh "$i" "[=10=]" "" "" "" "" "$f" &
(( i++ ))
done