【问题标题】:Using find within a for loop to extract portion of file names as a variable (bash)在 for 循环中使用 find 将文件名的一部分提取为变量(bash)
【发布时间】:2015-11-12 00:52:47
【问题描述】:

我有许多文件,它们的名称中有一条有用的信息,我想将它们提取为变量并在后续步骤中使用。文件名的结构是 samplename_usefulbit_junk。我正在尝试使用文件名(样本名)的可预测部分来遍历这些文件,将整个名称存储在一个变量中,并使用sed 来提取有用的位。这没用。

    samples="sample1 sample2 sample3"
    for i in $samples; do
       filename="$(find ./$FILE_DIR -maxdepth 1 -name '$(i)*' -printf '%f\n')"
       usefulbit="$(find ./$FILE_DIR -maxdepth 1 -name '$(i)*' -printf '%f\n' | sed 's/.*samplename//g' | sed 's/junk.*//g')"
       (More steps using $usefulbit or $(usefulbit) or ${usefulbit} or something)
    done

find ./$FILE_DIR -maxdepth 1 -name 'sample1*' -printf '%f\n'find ./$FILE_DIR -maxdepth 1 -name "sample1*" -printf '%f\n' 都可以工作,但是括号、花括号或单引号、双引号或反引号的组合无法使循环正常工作。这哪里出错了?

【问题讨论】:

    标签: bash variables for-loop find


    【解决方案1】:

    试试这个:

    for file in `ls *_*_*.*`
    do
      echo "Full file name is: $file"
      predictable_portion_filename=${file_%%_*}
      echo "predictable portion in the filename is: ${predictable_portion_filename}"
      echo "---"
    done
    

    PS: $variable 或 ${variable} 或 "${variable}" 或 "$variable" 与 $(variable) 不同,因为在最后一种情况下,$( ... ) 创建了一个子 shell 并处理里面的任何东西作为命令,即 $(variable) 将使子 shell 执行名为 variable

    的命令

    代替 ls __.,您还可以使用(以递归方式查找具有该标准文件名的所有文件):ls -1强>R *_*_*.*

    代替使用 ${file%%_*} 您还可以使用:echo ${file} | cut -d'_' -f1 得到可预测的值。您也可以使用各种其他方式(awk、sed/ 等)。

    【讨论】:

    • 谢谢,这对我帮助很大。这就是我最终使用的:for i in directory/*.ext; do myfile="$i" name="$(echo $i | sed 's!.*/!!g' | sed 's/_junk*.ext//g')" some other steps done
    【解决方案2】:

    对不起,我不能用 bash 来做,我可以告诉你另一种方法吗?这是我正在开发的外壳(lua-shell),以及作为您案例解决方案的演示:

    wws$ `ls ./demo/2
    sample1_red_xx.png  sample2_green_xx.png  sample3_blue_xx.png
    
    wws$ source ./demo/2.lua
    sample1_red_xx.png: red
    sample2_green_xx.png: green
    sample3_blue_xx.png: blue
    
    wws$ 
    

    我真的很想知道你的整个计划,除非你需要 bash 作为唯一的工具...... 呃,我忘记粘贴脚本了:

    samples={"sample1", "sample2", "sample3"}
    files = lfs.collect("./demo/2")
    
    function get_filename(prefix) 
        for i, file in pairs(files) do
            if string.match(file.name, prefix) then return file.name end
        end
    end
    for i = 1, #samples do
        local filename = get_filename(samples[i])       
        vim:set(filename)
        :f_lvf_hy
        print(filename ..": "..  vim:clipboard())
    end
    

    “get_filename()”似乎有点冗长……我还没有完成 lfs 组件。

    【讨论】:

    • 感谢您抽出宝贵时间回答我的问题!我对你的一些建议不太熟悉,无法将它们融入我正在尝试做的事情,但我找到了一个更简单的解决方案,适合我的目的。
    【解决方案3】:

    我不确定用我的最终解决方案回答我自己的问题是否是适当的 stackoverflow 礼仪,但这最终对我有用:

        for i in directory/*.ext; do
            myfile="$i"
            name="$(echo $i | sed 's!.*/!!g' | sed 's/_junk*.ext//g')"
            some other steps
        done
    

    这样我从文件名开始就已经是一个变量(在一个变量中?),而不必为find 及其强烈的意见而苦恼。它还使我不必列出样本名称。

    第一个sed 删除目录/,第二个删除文件名和扩展名的结尾,留下一个变量$name,我在后续步骤中生成其他文件时将其用作前缀。简单多了!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-20
      • 1970-01-01
      • 1970-01-01
      • 2017-06-30
      • 2022-11-03
      相关资源
      最近更新 更多