Bash:如何将具有相同名称的多个文件复制到多个文件夹

时间:2016-11-25 12:59:16

标签: bash copy copy-paste

我正在使用Linux机器。 我有很多名为相同的文件,目录结构如下:

P45_input_foo/result.dat
P45_input_bar/result.dat
P45_input_tar/result.dat
P45_input_cool/result.dat ...

很难一个一个地复制它们。我想将它们复制到另一个名为data的文件夹中,文件夹名称和文件名相同:

/data/foo/result.dat
/data/bar/result.dat
/data/tar/result.dat
/data/cool/result.dat ...

而不是一个一个地复制它们我应该做什么?

3 个答案:

答案 0 :(得分:1)

您需要在“_”之后提取第3项:

  

P45_input_foo - > FOO

创建目录(如果需要)并将文件复制到该目录。像这样的东西(未经过测试,可能需要编辑):

 STARTING_DIR="/"
cd "$STARTING_DIR"
VAR=$(ls -1)
while read DIR; do
  TARGET_DIR=$(echo "$DIR" | cut -d'_' -f3)
  NEW_DIR="/data/$DIR"
  if [ ! -d "$NEW_DIR" ]; then
    mkdir "$NEW_DIR"
  fi
  cp "$DIR/result.dat" "$NEW_DIR/result.dat"
  if [ $? -ne 0 ];
    echo "ERROR: encountered an error while copying"
  fi
done <<<"$VAR"

说明:假设您提到的所有路径都在根/下(如果不相应地更改STARTING_PATH)。使用ls获取目录列表,将输出存储在VAR中。将VAR的内容传递给while循环。

答案 1 :(得分:1)

在bash中使用for循环:

# we list every files following the pattern : ./<somedirname>/<any file>
# if you want to specify a format for the folders, you could change it here
# i.e. for your case you could write 'for f in P45*/*' to only match folders starting by P45 
for f in */*
do
    # we strip the path of the file from its filename
    # i.e. 'P45_input_foo/result.dat' will become 'P45_input_foo'
    newpath="${f%/*}"

    # mkdir -p /data/${newpath##*_} will create our new data structure
    # - /data/${newpath##*_} extract the last chain of character after a _, in our example, 'foo'
    # - mkdir -p will recursively create our structure
    # - cp "$f" "$_" will copy the file to our new directory. It will not launch if mkdir returns an error
    mkdir -p /data/${newpath##*_} && cp "$f" "$_"
done

${newpath##*_}${f%/*}用法是Bash字符串操作方法的一部分。您可以阅读更多相关信息here

答案 2 :(得分:1)

有点find并且有一些bash技巧,下面的脚本可以帮到你。请记住在没有mv的情况下运行脚本,并查看"/data/"$folder"/"是否是您要移动文件的实际路径。

#!/bin/bash

while IFS= read -r -d '' file
do

    fileNew="${file%/*}"       # Everything before the last '\'
    fileNew="${fileNew#*/}"    # Everything after the last '\'

    IFS="_" read _ _ folder <<<"$fileNew"

    mv -v "$file"  "/data/"$folder"/"

done < <(find . -type f -name "result.dat" -print0)