Shell 用于将文件夹名称复制并添加到多个子目录中的文件的脚本
Shell script to copy and prepend folder name to files from multiple subdirectories
我有几个共享文件名的不同图片的文件夹,文件夹结构如下:
/parent/folder001/img001.jpg
/parent/folder001/img002.jpg
/parent/folder002/img001.jpg
/parent/folder002/img002.jpg
/parent/folder003/img001.jpg
/parent/folder003/img002.jpg
...
并想copy/rename将这些文件放入一个新文件夹中,如下所示:
/newfolder/folder001_img001.jpg
/newfolder/folder001_img002.jpg
/newfolder/folder002_img001.jpg
/newfolder/folder002_img002.jpg
/newfolder/folder003_img001.jpg
/newfolder/folder003_img002.jpg
...
(如果 newfolder 不是父文件夹的子文件夹可能会更好,因为这最终可能会导致非常奇怪的递归。)
None 个包含图像的文件夹有任何子文件夹。
理想情况下,我希望能够将脚本重新用于 "update" 新文件夹,因为稍后我可能需要添加更多包含图像的文件夹。
如何使用 shell 脚本完成此操作?
我会使用这样的东西:
find -type f -exec sh -c 'f={}; fnew=$(rev <<< "$f" | sed 's~/~_~' | rev); echo "mv $f $fnew"' \;
这会在当前目录结构中查找文件并执行以下操作:
- 获取文件名
- 将最后一个
/
替换为 _
。
- 写
echo "cp $old_file $new_file"
一旦你有 运行 这个并且看到它打印了正确的命令,删除 echo
以便它有效地执行 mv
命令。
我知道 fnew=$(rev <<< "$f" | sed 's~/~_~' | rev)
有点难看,但我找不到更好的方法将最后一个 /
替换为 _
。也许 sed -r 's~/([^/]*)$~_~'
也可以,但我总是喜欢使用 rev
:)
由于您的 find
在 -sh c
表达式中表现不佳,让我们为它使用一个 while
循环:
while read -r file
do
new_file=$(rev <<< "$file" | sed 's~/~_~' | rev)
echo "mv $file $new_file"; done < <(find . -type f)
done < <(find . -type f)
单线:
while read -r file; do new_file=$(rev <<< "$file" | sed 's~/~_~' | rev); echo "mv $file $new_file"; done < <(find . -type f)
这有点乏味,但可以:
#!/bin/bash
parent=/parent
newfolder=/newfolder
mkdir "$newfolder"
for folder in "$parent"/*; do
if [[ -d "$folder" ]]; then
foldername="${folder##*/}"
for file in "$parent"/"$foldername"/*; do
filename="${file##*/}"
newfilename="$foldername"_"$filename"
cp "$file" "$newfolder"/"$newfilename"
done
fi
done
将 parent 路径放入 parent
变量,将 newfolder 路径放入 newfolder
变量。
救援功能,更新 Jahid 的脚本:
function updateFolder
{
mkdir ""
for folder in ""/*; do
if [[ -d $folder ]]; then
foldername="${folder##*/}"
for file in ""/"$foldername"/*; do
filename="${file##*/}"
newfilename="$foldername"_"$filename"
cp "$file" ""/"$newfilename"
done
fi
done
}
用过:
$ updateFolder /parent /newfolder
cd parent
for i in \*/*;do mv ${i} newfolder/\`dirname ${i}\`_\`basename ${i}\`;done
mv newfolder \<whereeveryouwant>
我有几个共享文件名的不同图片的文件夹,文件夹结构如下:
/parent/folder001/img001.jpg
/parent/folder001/img002.jpg
/parent/folder002/img001.jpg
/parent/folder002/img002.jpg
/parent/folder003/img001.jpg
/parent/folder003/img002.jpg
...
并想copy/rename将这些文件放入一个新文件夹中,如下所示:
/newfolder/folder001_img001.jpg
/newfolder/folder001_img002.jpg
/newfolder/folder002_img001.jpg
/newfolder/folder002_img002.jpg
/newfolder/folder003_img001.jpg
/newfolder/folder003_img002.jpg
...
(如果 newfolder 不是父文件夹的子文件夹可能会更好,因为这最终可能会导致非常奇怪的递归。)
None 个包含图像的文件夹有任何子文件夹。
理想情况下,我希望能够将脚本重新用于 "update" 新文件夹,因为稍后我可能需要添加更多包含图像的文件夹。
如何使用 shell 脚本完成此操作?
我会使用这样的东西:
find -type f -exec sh -c 'f={}; fnew=$(rev <<< "$f" | sed 's~/~_~' | rev); echo "mv $f $fnew"' \;
这会在当前目录结构中查找文件并执行以下操作:
- 获取文件名
- 将最后一个
/
替换为_
。 - 写
echo "cp $old_file $new_file"
一旦你有 运行 这个并且看到它打印了正确的命令,删除 echo
以便它有效地执行 mv
命令。
我知道 fnew=$(rev <<< "$f" | sed 's~/~_~' | rev)
有点难看,但我找不到更好的方法将最后一个 /
替换为 _
。也许 sed -r 's~/([^/]*)$~_~'
也可以,但我总是喜欢使用 rev
:)
由于您的 find
在 -sh c
表达式中表现不佳,让我们为它使用一个 while
循环:
while read -r file
do
new_file=$(rev <<< "$file" | sed 's~/~_~' | rev)
echo "mv $file $new_file"; done < <(find . -type f)
done < <(find . -type f)
单线:
while read -r file; do new_file=$(rev <<< "$file" | sed 's~/~_~' | rev); echo "mv $file $new_file"; done < <(find . -type f)
这有点乏味,但可以:
#!/bin/bash
parent=/parent
newfolder=/newfolder
mkdir "$newfolder"
for folder in "$parent"/*; do
if [[ -d "$folder" ]]; then
foldername="${folder##*/}"
for file in "$parent"/"$foldername"/*; do
filename="${file##*/}"
newfilename="$foldername"_"$filename"
cp "$file" "$newfolder"/"$newfilename"
done
fi
done
将 parent 路径放入 parent
变量,将 newfolder 路径放入 newfolder
变量。
救援功能,更新 Jahid 的脚本:
function updateFolder
{
mkdir ""
for folder in ""/*; do
if [[ -d $folder ]]; then
foldername="${folder##*/}"
for file in ""/"$foldername"/*; do
filename="${file##*/}"
newfilename="$foldername"_"$filename"
cp "$file" ""/"$newfilename"
done
fi
done
}
用过:
$ updateFolder /parent /newfolder
cd parent
for i in \*/*;do mv ${i} newfolder/\`dirname ${i}\`_\`basename ${i}\`;done
mv newfolder \<whereeveryouwant>