在 for 循环中使用 find 将部分文件名提取为变量 (bash)

Using find within a for loop to extract portion of file names as a variable (bash)

我有许多文件,它们的名称中包含一条有用的信息,我想将其提取为变量并在后续步骤中使用。文件名的结构是 samplename_usefulbit_junk。我试图使用文件名的可预测部分 (samplename) 遍历这些文件,将整个名称存储在一个变量中,并使用 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' 都有效,但是括号、大括号或单引号、双引号或反引号的组合都无法使循环起作用。这是哪里出了问题?

试试这个:

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 or ${variable} or "${variable}" or "$variable" 不同于 $(variable) 在最后一种情况下,$( ... ) 使得一个 sub-shell 并将其中的任何内容视为命令,即 $(variable) 将使 sub-shell 执行名为 variable[=11= 的命令]

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

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

对不起,我无法使用 bash,我可以向您展示另一种方法吗?这是我正在开发的 shell (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 组件。

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

    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,我在后续步骤中生成其他文件时将其用作前缀。简单多了!