如何添加计数器以查找 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

如果您只想递归遍历目录,则无需使用 findxargs

i=0
shopt -s globstar
for f in cobacoba/**; do
  [[ -f $f ]] || continue
  (( i > 5 )) && wait
  script.sh "$i" "[=10=]" "" "" "" "" "$f" &
  (( i++ ))
done