Linux bash:如何仅将文件名传输/复制到不同的相似文件?

Linux bash:如何仅将文件名传输/复制到不同的相似文件?,linux,bash,shell,Linux,Bash,Shell,我在文件夹a中有一些文件,它们的名称如下: 001_file.xyz 002_file.xyz 003_file.xyz 在单独的文件夹B中,我有如下文件: 001_FILE_somerandomtext.zyx 002_FILE_somerandomtext.zyx 003_FILE_somerandomtext.zyx renameFromDir() { useNamesFromDir=$1 forFilesFromDir=$2 for f in "$forFilesFro

我在文件夹a中有一些文件,它们的名称如下:

001_file.xyz
002_file.xyz
003_file.xyz
在单独的文件夹B中,我有如下文件:

001_FILE_somerandomtext.zyx
002_FILE_somerandomtext.zyx
003_FILE_somerandomtext.zyx
renameFromDir() {
  useNamesFromDir=$1
  forFilesFromDir=$2

  for f in "$forFilesFromDir"/*; do

    # Put original extension in $f_ext
    f_ext=${f##*.}

    # Put number in $f_num
    f_num=${f##*/}; f_num=${f_num%%_*}

    # look for a file in directory B with same number
    set -- "$useNamesFromDir"/"${f_num}"_*.*
    [[ $1 && -e $1 ]] || {
      echo "Could not find file number $f_num in $dirB" >&2
      continue
    }
    (( $# > 1 )) && {
      # there's more than one file with the same number; write an error
      echo "Found more than one file with number $f_num in $dirB" >&2
      printf '  - %q\n' "$@" >&2
      continue
    }

    # extract the parts of our destination filename we want to keep
    destName=${1##*/}       # remove everything up to the last /
    destName=${destName%.*} # and past the last .

    # write the command we would run to stdout
    printf '%q ' mv "$f" "$forFilesFromDir/$destName.$f_ext"; printf '\n'
    ## or uncomment this to actually run the command
    # mv "$f" "$forFilesFromDir/$destName.$f_ext"
  done
}
现在,如果可能的话,我想用bash中的一个命令行重命名文件夹B中的所有文件以及文件夹a中的文件名。文件扩展名必须保持不同。 每个文件夹A和B中的文件数量完全相同,并且由于编号原因,它们的顺序相同

我是个彻头彻尾的傻瓜,但我希望这个问题能有一些简单的答案

提前谢谢

ZVLKX


*为澄清而编辑的示例

一个实现可能看起来有点像这样:

001_FILE_somerandomtext.zyx
002_FILE_somerandomtext.zyx
003_FILE_somerandomtext.zyx
renameFromDir() {
  useNamesFromDir=$1
  forFilesFromDir=$2

  for f in "$forFilesFromDir"/*; do

    # Put original extension in $f_ext
    f_ext=${f##*.}

    # Put number in $f_num
    f_num=${f##*/}; f_num=${f_num%%_*}

    # look for a file in directory B with same number
    set -- "$useNamesFromDir"/"${f_num}"_*.*
    [[ $1 && -e $1 ]] || {
      echo "Could not find file number $f_num in $dirB" >&2
      continue
    }
    (( $# > 1 )) && {
      # there's more than one file with the same number; write an error
      echo "Found more than one file with number $f_num in $dirB" >&2
      printf '  - %q\n' "$@" >&2
      continue
    }

    # extract the parts of our destination filename we want to keep
    destName=${1##*/}       # remove everything up to the last /
    destName=${destName%.*} # and past the last .

    # write the command we would run to stdout
    printf '%q ' mv "$f" "$forFilesFromDir/$destName.$f_ext"; printf '\n'
    ## or uncomment this to actually run the command
    # mv "$f" "$forFilesFromDir/$destName.$f_ext"
  done
}

现在,我们如何测试这个呢

mkdir -p A B
touch A/00{1,2,3}_file.xyz B/00{1,2,3}_FILE_somerandomtext.zyx
renameFromDir A B
鉴于此,输出为:

mv B/001_FILE_somerandomtext.zyx B/001_file.zyx
mv B/002_FILE_somerandomtext.zyx B/002_file.zyx
mv B/003_FILE_somerandomtext.zyx B/003_file.zyx

如果这没有帮助,很抱歉,但我写得很开心。
这会将文件夹B中的项目重命名为文件夹A中的名称,保留文件夹B的扩展名。


这很简单(sorta——有很多细节您没有指定;
FILE
FILE
是两个常量字符串,还是名称需要单独匹配才能正确?扩展名总是常量吗?),但这也不是软件开发问题。考虑一下,而不是StackOverflow。谢谢你,查尔斯。很抱歉在错误的平台发布。我刚在这里找到一个,所以我也试着问<代码>文件和
文件
实际上不是常数,但文件不必匹配在一起,因为它们已经正确编号。因此,B中的第一个文件需要用A中第一个文件的文件名重命名,以此类推……我的意思是,如果您只想将任何与regex
文件(.*)([:digit:]]+.zyx
匹配的内容重命名为
文件\u2.xyz
(其中
\2
是regex中与原始名称匹配的第二组),这是100%微不足道的,许多操作系统发行版附带的
rename
命令将立即执行。如果名称不同,请确保在测试数据中反映这一点,这样人们就不会编写依赖于测试数据中未反映在实时数据中的模式的答案!好的,我明白了。在那件事上,我的例子并不准确。更好的可能是:文件夹A:
001\u file.xyz
002\u file.xyz
003\u file.xyz
文件夹B:
001\u file\u random.zyx
002\u file\u random.zyx
003\u file\u random.zyx
我还确信
rename
cp
命令会完成这项工作,我只是不知道如何在不同位置的多个文件上使用它们。我试图找出答案,但直到现在还没有结果,我找不到任何例子为我的用例。但是,除此之外还有一些其他问题--…如果您在
a
B
目录中创建一个名称中带有空格的文件,您将看到
FILES\u in_a
FILES\u in_B
将空格两侧的内容拆分为两个单独的单词。在这一点上,请参见中的条目#1。类似地,基于分词(正如您在这里所做的)将字符串扩展到数组是不安全的,因为合法文件名可以包含NUL以外的任何字符。从
find
将输出读取到数组中的安全方法是使用
print0
生成NUL分隔的流,如
中的IFS=read-r-d''文件名;do数组+=(“$filename”);完成后,
==
也不能保证在POSIX
测试中工作。如果阅读,您会注意到,
=
是唯一指定的/兼容的字符串比较运算符。此外,所有caps变量名称的格式都不正确——环境变量的POSIX命名约定指定所有caps名称都用于对系统或shell有意义的变量,至少有一个小写字符的名称保留给应用程序使用。由于使用与环境变量重叠的名称设置shell变量会自动将该变量导出到环境中(覆盖先前存在的shell变量),因此此命名约定也适用于shell变量。