【问题标题】:append folder name to file name when copying-space in folder name [duplicate]在文件夹名称中复制空格时将文件夹名称附加到文件名[重复]
【发布时间】:2018-09-06 10:12:30
【问题描述】:

我一直在使用循环将数据从外部组复制到我的工作目录,将文件夹名称附加到文件名的开头。 for 循环基于这个先前的问题。 Append part of folder name to all .gz within

自从我提出这个问题以来,外部小组简化了他们的文件夹结构,但现在在一些文件夹名称中添加了“(2)”(我无法影响小组命名他们文件的方式,这是一个巨大的公司)。空间打破了我的循环,我需要帮助修复它。

外部组的文件结构

  Samples/SampleName1/Files/SampleID1_uniqueNumber.gz
  Samples/SampleName2/Files/SampleID2_uniqueNumber.gz
  Samples/SampleName3/Files/SampleID3_uniqueNumber.gz
  Samples/SampleName3 (2)/Files/SampleID3_uniqueNumber.gz

我想要的目标文件夹中的内容(所有样本都移动到单个目标)

  SampleName1.SampleID1_uniqueNumber.gz
  SampleName2.SampleID2_uniqueNumber.gz
  SampleName3.SampleID3_uniqueNumber.gz
  SampleName3.SampleID3_uniqueNumber.gz

我当前的 for 循环可以正确复制除最后一个样本之外的所有内容。 uniqueNumber 应该足够唯一以防止 2 SampleName3 相互覆盖。

   for f in ../pathToData/Samples/*/Files/*.gz;
    do s=${f##../pathToData/Samples/}; 
    s=${s%%/*};
    cp $f "/destinationFolder/"$s"."${f##*Files/};
    done

如何转义空格,以便 cp 将“(2)”视为原始文件名的一部分,而不是将“(2)”视为目标文件夹?

【问题讨论】:

    标签: string bash for-loop


    【解决方案1】:

    与某些编程语言不同,bash 可以在引号内进行变量替换。要将变量作为单个参数传递,请将其括在引号中:

    cp "$f" [...]
    

    这也适用于命令的其余部分。可以改写为:

    cp "$f" "/destinationFolder/$s.${f##*Files/}";
    

    【讨论】:

    • 似乎太简单了,我没有想到参数扩展在引号内起作用。谢谢!
    • 差不多了,需要去掉目标文件名中的“(2)”。
    • 这是一个单独的问题,因此您应该将此问题重新标记为已回答并打开一个新问题。不过,请随时在您的新问题中链接回此问题。
    【解决方案2】:

    如果你想这样做你的方式

    for f in Samples/*/Files/*.gz; do
        s=${f##Samples/};
        s=${s%%/*};
        [[ $s =~ [[:space:]] ]] && continue
        echo cp "$f" "/destinationFolder/$s.${f##*Files/}"
    done
    

    (当echo命令看起来足够好时删除它)

    但是你不需要任何循环,请看一下:

    输入:

    (你有一个欺骗文件:SampleName3.SampleID3_uniqueNumber.gz

    $ tree Samples/
    Samples/
    ├── SampleName1
    │   └── Files
    │       └── SampleID1_uniqueNumber.gz
    ├── SampleName2
    │   └── Files
    │       └── SampleID2_uniqueNumber.gz
    ├── SampleName3
    │   └── Files
    │       └── SampleID3_uniqueNumber.gz
    └── SampleName3 (2)
        └── Files
            └── SampleID3_uniqueNumber.gz
    
    8 directories, 4 files
    

    shell 中使用 perl 的 的代码:

    $ shopt -s globstar # enable recursion with '**' require bash --version >= 4
    $ rename -n 's|^[^/]+/([^/\s]+)/Files/(.*\.gz)|$1.$2|' Samples/**/*.gz
    

    输出:

    Samples/SampleName1/Files/SampleID1_uniqueNumber.gz -> SampleName1.SampleID1_uniqueNumber.gz
    Samples/SampleName2/Files/SampleID2_uniqueNumber.gz -> SampleName2.SampleID2_uniqueNumber.gz
    Samples/SampleName3/Files/SampleID3_uniqueNumber.gz -> SampleName3.SampleID3_uniqueNumber.gz
    

    当输出看起来不错时移除-n开关。

    还有其他同名的工具可能会也可能不会做到这一点,所以要小心。

    如果您运行以下命令 (GNU)

    $ file "$(readlink -f "$(type -p rename)")"
    

    而您的结果包含Perl script, ASCII text executable 而不包含ELF,那么这似乎是正确的工具 =)

    如果不是,则将其设为 Debian 和派生类 Ubuntu 的默认值(通常已经如此):

    $ sudo update-alternatives --set rename /path/to/rename
    

    /path/to/rename 替换为您的perl rename 可执行文件的路径。


    如果你没有这个命令,搜索你的包管理器来安装它或do it manually(没有deps...)


    这个工具最初是由 Perl 的父亲 Larry Wall 编写的。

    【讨论】:

    • 对于这个任务,我更喜欢使用不需要更新或特殊安装的工具,因为我正在尝试编写可供命令行经验很少的人使用的简单命令(我的问题中没有的信息)。但是谢谢你的例子。
    • 我提供了两种方法,第一种是你的
    猜你喜欢
    • 1970-01-01
    • 2020-08-29
    • 1970-01-01
    • 2021-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多