Process files in pairs

此生再无相见时 提交于 2019-12-08 07:03:03

问题


I have a list of files:

file_name_FOO31101.txt
file_name_FOO31102.txt
file_name_FOO31103.txt
file_name_FOO31104.txt

And I want to use pairs of files for input into a downstream program such as:

program_call file_name_01.txt file_name_02.txt
program_call file_name_03.txt file_name_04.txt
...

I do not want:

program_call file_name_02.txt file_name_03.txt

I need to do this in a loop as follows:

#!/bin/bash

FILES=path/to/files

for file in $FILES/*.txt;

do

    stem=$( basename "${file}" ) # stem : file_name_FOO31104_info.txt
    output_base=$( echo $stem | cut -d'_' -f 1,2,3 )  # output_base : FOO31104_info.txt
    id=$( echo $stem | cut -d'_' -f 3 ) # get the first field : FOO31104
    number=$( echo -n $id | tail -c 2 ) # get the last two digits : 04

     echo $id $((id+1))

done

But this does not produce what I want.

In each loop I want to call a program once, with two files as input (last 2 digits of first file always odd 01, last 2 digits of second file always even 02)


回答1:


I actually wouldn't use a for loop at all. A while loop that shifts files off is a perfectly reasonable way to do this.

# here, we're overriding the argument list with the list of files
# ...you can do this in a function if you want to keep the global argument list intact
set -- "$FILES"/*.txt                 ## without these quotes paths with spaces break

# handle the case where no files were found matching our glob
[[ -e $1 || -L $1 ]] || { echo "No .txt found in $FILES" >&2; exit 1; }

# here, we're doing our own loop over those arguments
while (( "$#" > 1 )); do              ## continue in the loop only w/ 2-or-more remaining
  echo "Processing files $1 and $2"   ## ...substitute your own logic here...
  shift 2 || break                    ## break even if test doesn't handle this case
done

# ...and add your own handling for the case where there's an odd number of files.
(( "$#" )) && echo "Left over file $1 still exists"

Note that the $#s are quoted inside (( )) here for StackOverflow's syntax highlighting, not because they otherwise need to be. :)


By the way -- consider using bash's native string manipulation.

stem=${file##*/}
IFS=_ read -r p1 p2 id p_rest <<<"$stem"
number=${id:$(( ${#id} - 2 ))}
output_base="${p1}${p2}${id}"
echo "$id $((10#number + 1))" # 10# ensures interpretation as decimal, not octal


来源:https://stackoverflow.com/questions/41618084/process-files-in-pairs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!