成对处理文件 [英] Process files in pairs

查看:178
本文介绍了成对处理文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个文件列表:

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

我想使用一对文件输入到下游程序如:

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

我不想:

  program_call file_name_02.txt file_name_03.txt 

我需要

$ p $ #!/ bin / bash

FILES =路径/ to / files

用于$ FILES / *。txt文件;


$ b $ 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)#获取第一个字段:FOO31104
number = $(echo -n $ id | tail -c 2)#得到最后两位:04
$ b $ echo $ id $((id + 1))

完成

但是这不会产生我想要的。

在每个循环中,我要调用一次程序,并输入两个文件(第一个文件的最后两个数字总是奇数 01 ,第二个文件的最后两个数字总是偶数 02

解决方案

实际上我根本不会使用作为循环。 while 循环 shift s files off是完全合理的方式。

 #在这里,我们用文件列表
#覆盖参数列表... ...如果你想要的话,你可以在函数中做到这一点保持全局参数列表完好
set - $ FILES/ *。txt ##没有这些引号路径与空格破解

#处理没有找到匹配我们的文件的情况glob
[[-e $ 1 || -L $ 1]] || {echo$ FILES中找不到.txt>& 2;出口1; ($$#> 1));

在这里,我们正在做自己的循环, do ##在循环中只有w / 2或更多剩余
echo正在处理文件$ 1和$ 2## ...在这里替换你自己的逻辑...
shift 2 || break ##即使测试不处理这种情况,也可以打破
完成

#...并为有奇数个文件的情况添加自己的处理。
(($#))&&回声遗留文件$ 1仍然存在

请注意 $# / code> s在这里引用(())在StackOverflow的语法突出显示,而不是因为他们需要。 :)






顺便说一句 - 考虑使用bash的本地字符串操作。 $ b

  stem = $ {file ## * /} 
IFS = _ read -r p1 p2 id p_rest <<< $ $
$ number $ $ $($ {#id} - 2))}
output_base =$ {p1} $ {p2} $ {id}
echo$ id $ ((10#number + 1))#10#确保解释为十进制,不是八进制


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)

解决方案

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

这篇关于成对处理文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆