I have several folders with different images sharing file names, with a folder structure like this:
我有几个文件夹,不同的图像共享文件名,文件夹结构如下:
/parent/folder001/img001.jpg
/parent/folder001/img002.jpg
/parent/folder002/img001.jpg
/parent/folder002/img002.jpg
/parent/folder003/img001.jpg
/parent/folder003/img002.jpg
...
and would like to copy/rename these files into a new folder, like this:
并希望将这些文件复制/重命名为新文件夹,如下所示:
/newfolder/folder001_img001.jpg
/newfolder/folder001_img002.jpg
/newfolder/folder002_img001.jpg
/newfolder/folder002_img002.jpg
/newfolder/folder003_img001.jpg
/newfolder/folder003_img002.jpg
...
(It's probably better if newfolder isn't a subfolder of parent, since that might end up causing really weird recursion.)
(如果newfolder不是父文件夹的子文件夹,那可能会更好,因为这可能最终导致非常奇怪的递归。)
None of the folders containing images have any subfolders.
包含图像的文件夹都没有任何子文件夹。
Ideally, I'd like to be able to reuse the script to "update" newfolder, since I might need to add more folders-containing-images later along the line.
理想情况下,我希望能够重用该脚本来“更新”新文件夹,因为我可能需要在以后添加更多包含文件夹的图像。
How can I accomplish this with a shell script?
如何使用shell脚本完成此操作?
3 个解决方案
#1
3
This is a bit tedious but will do:
这有点乏味但会做:
#!/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
Put the parent path to parent
variable and newfolder path to newfolder
variable.
将父路径设置为父变量,将newfolder路径设置为newfolder变量。
#2
3
functions to the rescue, updating Jahid's script:
救援功能,更新Jahid的脚本:
function updateFolder
{
mkdir "$2"
for folder in "$1"/*; do
if [[ -d $folder ]]; then
foldername="${folder##*/}"
for file in "$1"/"$foldername"/*; do
filename="${file##*/}"
newfilename="$foldername"_"$filename"
cp "$file" "$2"/"$newfilename"
done
fi
done
}
used:
$ updateFolder /parent /newfolder
#3
2
I would use something like this:
我会用这样的东西:
find -type f -exec sh -c 'f={}; fnew=$(rev <<< "$f" | sed 's~/~_~' | rev); echo "mv $f $fnew"' \;
This looks for files within the current directory structure and perform the following:
这将查找当前目录结构中的文件并执行以下操作:
- get the file name
- replace the last
/
with_
. - write
echo "cp $old_file $new_file"
获取文件名
用_替换最后一个/。
写回声“cp $ old_file $ new_file”
Once you have run this and seen it prints the proper command, remove the echo
so that it effectively does the mv
command.
一旦你运行它并看到它打印正确的命令,删除回声,以便它有效地执行mv命令。
I know the fnew=$(rev <<< "$f" | sed 's~/~_~' | rev)
is a bit ugly trick, but I couldn't find a better way to replace the last /
with _
. Maybe sed -r 's~/([^/]*)$~_\1~'
could also be appropiate, but I always like using rev
:)
我知道fnew = $(rev <<<“$ f”| sed's〜/ ~_~'| rev)是一个有点难看的伎俩,但我找不到更好的方法来替换最后一个/用_ 。也许sed -r的〜/([^ /] *)$ ~_ \ 1~'也可能是合适的,但我总是喜欢使用rev :)
Since your find
does not behave well with the -sh c
expression, let's use a while
loop for it:
由于你的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)
As a one-liner:
作为单线:
while read -r file; do new_file=$(rev <<< "$file" | sed 's~/~_~' | rev); echo "mv $file $new_file"; done < <(find . -type f)
#1
3
This is a bit tedious but will do:
这有点乏味但会做:
#!/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
Put the parent path to parent
variable and newfolder path to newfolder
variable.
将父路径设置为父变量,将newfolder路径设置为newfolder变量。
#2
3
functions to the rescue, updating Jahid's script:
救援功能,更新Jahid的脚本:
function updateFolder
{
mkdir "$2"
for folder in "$1"/*; do
if [[ -d $folder ]]; then
foldername="${folder##*/}"
for file in "$1"/"$foldername"/*; do
filename="${file##*/}"
newfilename="$foldername"_"$filename"
cp "$file" "$2"/"$newfilename"
done
fi
done
}
used:
$ updateFolder /parent /newfolder
#3
2
I would use something like this:
我会用这样的东西:
find -type f -exec sh -c 'f={}; fnew=$(rev <<< "$f" | sed 's~/~_~' | rev); echo "mv $f $fnew"' \;
This looks for files within the current directory structure and perform the following:
这将查找当前目录结构中的文件并执行以下操作:
- get the file name
- replace the last
/
with_
. - write
echo "cp $old_file $new_file"
获取文件名
用_替换最后一个/。
写回声“cp $ old_file $ new_file”
Once you have run this and seen it prints the proper command, remove the echo
so that it effectively does the mv
command.
一旦你运行它并看到它打印正确的命令,删除回声,以便它有效地执行mv命令。
I know the fnew=$(rev <<< "$f" | sed 's~/~_~' | rev)
is a bit ugly trick, but I couldn't find a better way to replace the last /
with _
. Maybe sed -r 's~/([^/]*)$~_\1~'
could also be appropiate, but I always like using rev
:)
我知道fnew = $(rev <<<“$ f”| sed's〜/ ~_~'| rev)是一个有点难看的伎俩,但我找不到更好的方法来替换最后一个/用_ 。也许sed -r的〜/([^ /] *)$ ~_ \ 1~'也可能是合适的,但我总是喜欢使用rev :)
Since your find
does not behave well with the -sh c
expression, let's use a while
loop for it:
由于你的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)
As a one-liner:
作为单线:
while read -r file; do new_file=$(rev <<< "$file" | sed 's~/~_~' | rev); echo "mv $file $new_file"; done < <(find . -type f)