【问题标题】:How do I move files into folders with similar names in Unix?如何在 Unix 中将文件移动到名称相似的文件夹中?
【发布时间】:2019-06-15 02:36:45
【问题描述】:

很抱歉,如果以前有人问过这个问题,我只是不知道如何将其作为搜索查询。

我有一组如下所示的文件夹:

Brain - Amygdala/                 Brain - Spinal cord (cervical c-1)/  Skin - Sun Exposed (Lower leg)/
Brain - Caudate (basal ganglia)/  Lung/                                Whole Blood/

我还有一组文件看起来像这样:

Brain_Amygdala.v7.covariates_output.txt                  Skin_Not_Sun_Exposed_Suprapubic.v7.covariates_output.txt
Brain_Caudate_basal_ganglia.v7.covariates_output.txt     Skin_Sun_Exposed_Lower_leg.v7.covariates_output.txt
Brain_Spinal_cord_cervical_c-1.v7.covariates_output.txt  Whole_Blood.v7.covariates_output.txt

如您所见,文件与其名称中的目录并不完全匹配。例如,Brain_Amygdala.v7.covariates_output.txtBrain - Amygdala/ 并不完全相同。即使我们要从协变量文件中删除组织名称,Brain_Amygdala 的格式也与其对应的文件夹不同。

Whole Blood/ 相同。它与Whole_Blood.v7.covariates_output.txt 不同,即使您要将组织名称从协变量文件Whole_Blood 中分离出来。

然而,我想做的是将这些组织文件中的每一个移动到它们相应的文件夹中。如果您注意到,协变量文件以文件名中第一个点 . 之前的组织命名。它们由下划线_ 分隔。 我当时的想法是分解文件名的第一个 . 之前的前几个单词,以便我可以轻松地将其移动到相应的文件中。

例如

Brain_Amygdala.v7.covariates_output.txt -> Brain*Amygdala [mv]-> Brain*Amygdala/

a) 我不知道如何隔离文件名中导致文件名中第一个 . 的第一个单词

b) 如果我这样做,我不知道如何在每个单词之间插入通配符并将其匹配到相应的文件夹。

但是,我完全愿意接受其他方式来做这样的事情。

【问题讨论】:

    标签: bash unix filenames mv


    【解决方案1】:

    不是一个完整的答案,但它应该可以解决您的一些问题:

    a) 隔离字符串的第一个单词,直到第一个 .:使用 Parameter Expansions

    string=Brain_Amygdala.v7.covariates_output.txt
    until_dot=${string%%.*}
    echo "$until_dot"
    

    将输出Brain_Amygdala(我们保存在变量until_dot中)。

    b) 您可能想使用${parameter/pattern/string} 参数扩展:

    # Replace all non-alphabetic characters by the glob *
    glob_pattern=${until_dot//[^[:alpha:]]/*}
    echo "$glob_pattern"
    

    将输出(与上面相同的变量)Brain*Amygdala

    c) 要使用所有这些:最好先确定可能的目标,然后进行一些基本检查:

    # Use nullglob to have non matching glob expand to nothing
    shopt -s nullglob
    # DO NOT USE QUOTES IN THE FOLLOWING EXPANSION:
    # the variable is actually a glob!
    # Could also do dirs=( $glob_pattern*/ ) to check if directory
    dirs=( $glob_pattern/ )
    
    # Now check how many matches there are:
    if ((${#dirs[@]} == 0)); then
        echo >&2 "No matches for $glob_pattern"
    elif ((${#dirs[@]} > 1)); then
        echo >&2 "More than one matches for $glob_pattern: ${dirs[@]}"
    else
        echo "All good!"
        # Remove the echo to actually perform the move
        echo mv "$string" "${dirs[0]}"
    fi
    

    我不知道您的数据将如何有效地符合这些要求,但我希望这个答案能真正回答您的一些问题! (要了解有关参数扩展的更多信息,请阅读并尝试使用我提供给您的参考链接)。

    【讨论】:

    • 再看一遍,我忽略了 c) 中的 glob 部分:可能想要 dirs=( $glob_pattern/ ) 甚至 dirs=( $glob_pattern*/ ),和/或在 mv 之前,检查目标确实是一个目录.
    • 只有一个问题:我在运行脚本时收到一条成功消息,但是当我检查文件夹内部时,我什么也没看到。我认为这是因为 Unix 将 Brain - Amygdala/ 视为三个独立的实体(Brain-Amygdala/)。无论如何,当echo mv "$string" "${dirs[0]}" 触发"${dirs[0]}" 时仍然用引号括起来?更好的是,有没有办法做到这一点,同时删除目录名称中的空格?谢谢你的帮助。这变得非常复杂,我只是想在mv 中包含文件和目录名称
    • 我现在得到的是mv Brain_Spinal_cord_cervical_c-1.v7.covariates_output.txt Brain - Spinal cord (cervical c-1)/,而我希望它是mv Brain_Spinal_cord_cervical_c-1.v7.covariates_output.txt "Brain - Spinal cord (cervical c-1)/"
    • @CelineDion 不要担心空格:是echo 语句去掉了引号。 mv 语句将接收给定的两个参数:我写的所有内容都被正确引用,以便按需要工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-03
    • 2013-01-15
    • 2022-11-25
    • 2023-03-17
    • 2016-11-06
    • 1970-01-01
    相关资源
    最近更新 更多