String 复制文件夹名中的空间时,将文件夹名附加到文件名

String 复制文件夹名中的空间时,将文件夹名附加到文件名,string,bash,for-loop,rename,bash4,String,Bash,For Loop,Rename,Bash4,我一直在使用循环将数据从外部组复制到我的工作目录,并将文件夹名附加到文件名的开头。for循环基于前面的问题。 因为我问了这个问题,外部组简化了他们的文件夹结构,但现在在一些文件夹名称中添加了“(2)”(我无法影响组命名文件的方式,这是一家大型公司)。空间打破了我的循环,我需要帮助修复它 外部组上的文件结构 Samples/SampleName1/Files/SampleID1_uniqueNumber.gz Samples/SampleName2/Files/SampleID2_uni

我一直在使用循环将数据从外部组复制到我的工作目录,并将文件夹名附加到文件名的开头。for循环基于前面的问题。

因为我问了这个问题,外部组简化了他们的文件夹结构,但现在在一些文件夹名称中添加了“(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
目标文件夹中所需的内容(所有样本移动到单个目标)

我的当前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)”视为目标文件夹?

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

cp "$f" [...]
这也适用于命令的其余部分。它可以重写为:

cp "$f" "/destinationFolder/$s.${f##*Files/}";
如果您想按自己的方式进行:

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

但您不需要任何循环,请看:

输入: (您有一个重复文件:
SampleName3.SampleID3\u uniqueNumber.gz

在shell中使用perl的代码: 输出: 当输出看起来良好时,移除
-n
开关

还有其他同名工具可能无法做到这一点,因此请小心。

如果运行以下命令(
GNU

您得到的结果包含
Perl脚本、ASCII文本可执行文件
,但不包含
ELF
,那么这似乎是正确的工具=)

如果不是,将其作为
Debian
和类似
Ubuntu
的衍生工具的默认值(通常已经是这种情况):

$ sudo update-alternatives --set rename /path/to/rename
/path/to/rename
替换为
perl rename
可执行文件的路径


如果您没有此命令,请搜索您的软件包管理器以安装它,或者(无deps…)



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

似乎太简单了,我没有想到参数扩展可以在引号中工作。谢谢差不多了,我需要去掉目标文件名中的“(2)”。这是一个单独的问题,因此您应该将此问题重新标记为已回答,然后打开一个新问题。不过,请随时在新问题中链接回此问题。对于此任务,我更喜欢使用不需要更新或特殊安装的工具,因为我正在尝试编写简单的命令,这些命令可供在命令行方面经验很少的人使用(我的问题中没有包含的信息)。但是谢谢你的例子。我提供了两种方法,第一种是你的
for f in Samples/*/Files/*.gz; do
    s=${f##Samples/};
    s=${s%%/*};
    [[ $s =~ [[:space:]] ]] && continue
    echo cp "$f" "/destinationFolder/$s.${f##*Files/}"
done
$ 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
$ 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
$ file "$(readlink -f "$(type -p rename)")"
$ sudo update-alternatives --set rename /path/to/rename