Bash: 如何将多个同名文件复制到多个文件夹
Bash: how to copy multiple files with same name to multiple folders
我正在 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 ...
我应该怎么做而不是一张一张地复制它们?
您需要提取“_”后的第三项:
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 循环。
在 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。
一点 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)
我正在 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 ...
我应该怎么做而不是一张一张地复制它们?
您需要提取“_”后的第三项:
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 循环。
在 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。
一点 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)