我正在尝试用 zsh (Linux Mint 21.3 “Virginia”) 编写一个脚本,将文件从 $source 移动(或复制)到 $target,但结果却令人困惑。我使用 yad 文件对话框来选择文件并命名目标目录。我能做到的最好的就是只将最终选择复制到空目标。
以下是整个脚本
setopt -x
setopt -v
autoload -Uz zmv
# WARNING Just because two or more files from different sources have identical names does not mean
#that the files are identical.
declare -a array
array=$(yad --width=600 --height=800 \
--title="Choose files to move." \
--file --multiple --separator='\n')
echo $array
target=$(yad --width=600 --height=800 \
--title="Choose destination." \
--file --directory)
echo "target="$target
# The file you wish to move may already exist in the target directory.
# If you do not want to overwrite it you can use
# mv -n
# mv --no-clobber
# or
# mv --backup=numbered
# Clumsy, but better than nothing, and doesn't give me what I want.
# That is why I wrote this script, it adds an incremented number to the name.
# eg <movie>.<ext>
# eg <movie>_copy1.<ext>
# eg <movie>_copy2.<ext>
# Yes, I could use brackets but they are illegal characters and I have a renamer
# that would remove them.
# You can't just use <filename>.$ext to check if the file exists in target because
# you'll miss any existing copies. You have to account for iteration.
for filename in $array; do
unset x
# decompose filename
# just name without path
filename=$filename:t
echo
echo
echo "filename="$filename
echo
echo
# name without extension
shortname=${filename%.*}
echo "shortname="$shortname
echo
echo
# extension
ext=${filename##*.}
echo
echo
echo "ext="$ext
# The key here is to rename the file (if necessary) BEFORE copying it to target instead
# of after.
# Does file already exist in $target? Count them.
x=$(find $target -iname "$shortname*.$ext" | wc -c)
echo
echo
echo "x="$x
# If no file exists, move to target.
# If one file exists then $x will return "1". Think of it as
# <filename>_copy0.<ext>,
# this makes the file you wish to move
# <filename>_copy1.<ext>, - the value of $x.
case $x in
0) cp $filename $target
sleep .2
;;
*) mv $filename $shortname_copy$x.$ext
cp $filename $target
sleep .2
;;
esac
done
exit 0
这是使用相同参数两次运行脚本的终端输出。
+/home/revision-6/bin/cpi:4> setopt -v
autoload -Uz zmv
+/home/revision-6/bin/cpi:5> autoload -Uz zmv
# WARNING Just because two or more files from different sources have identical names does not mean
#that the files are identical.
declare -a array
+/home/revision-6/bin/cpi:11> declare -a array
array=$(yad --width=600 --height=800 \
--title="Choose files to move." \
--file --multiple --separator='\n')
+/home/revision-6/bin/cpi:12> array=+/home/revision-6/bin/cpi:12> yad '--width=600' '--height=800' '--title=Choose files to move.' --file --multiple '--separator=\n'
(yad:3962282): dbind-WARNING **: 15:34:42.076: Couldn't connect to accessibility bus: Failed to connect to socket /root/.cache/at-spi/bus_0.0: Permission denied
+/home/revision-6/bin/cpi:12> array=$'/home/revision-6/Videos/betty_boop_a_song_a_day_1936.mkv\n/home/revision-6/Videos/betty_boop_is_my_palm_read_1932.mkv\n/home/revision-6/Videos/betty_boop_more_pep_1936.mkv'
echo $array
+/home/revision-6/bin/cpi:15> echo $'/home/revision-6/Videos/betty_boop_a_song_a_day_1936.mkv\n/home/revision-6/Videos/betty_boop_is_my_palm_read_1932.mkv\n/home/revision-6/Videos/betty_boop_more_pep_1936.mkv'
/home/revision-6/Videos/betty_boop_a_song_a_day_1936.mkv
/home/revision-6/Videos/betty_boop_is_my_palm_read_1932.mkv
/home/revision-6/Videos/betty_boop_more_pep_1936.mkv
target=$(yad --width=600 --height=800 \
--title="Choose destination." \
--file --directory)
+/home/revision-6/bin/cpi:17> target=+/home/revision-6/bin/cpi:17> yad '--width=600' '--height=800' '--title=Choose destination.' --file --directory
(yad:3962312): dbind-WARNING **: 15:34:54.949: Couldn't connect to accessibility bus: Failed to connect to socket /root/.cache/at-spi/bus_0.0: Permission denied
+/home/revision-6/bin/cpi:17> target=/home/revision-6/video_processing
echo "target="$target
+/home/revision-6/bin/cpi:20> echo 'target=/home/revision-6/video_processing'
target=/home/revision-6/video_processing
# The file you wish to move may already exist in the target directory.
# If you do not want to overwrite it you can use
# mv -n
# mv --no-clobber
# or
# mv --backup=numbered
# Clumsy, but better than nothing, and doesn't give me what I want.
# That is why I wrote this script, it adds an incremented number to the name.
# eg <movie>.<ext>
# eg <movie>_copy1.<ext>
# eg <movie>_copy2.<ext>
# Yes, I could use brackets but they are illegal characters and I have a renamer
# that would remove them.
# You can't just use <filename>.$ext to check if the file exists in target because
# you'll miss any existing copies. You have to account for iteration.
for filename in $array; do
unset x
# decompose filename
# just name without path
filename=$filename:t
echo
echo
echo "filename="$filename
echo
echo
# name without extension
shortname=${filename%.*}
echo "shortname="$shortname
echo
echo
# extension
ext=${filename##*.}
echo
echo
echo "ext="$ext
# The key here is to rename the file (if necessary) BEFORE copying it to target instead
# of after.
# Does file already exist in $target? Count them.
x=$(find $target -iname "$shortname*.$ext" | wc -c)
echo
echo
echo "x="$x
# If no file exists, move to target.
# If one file exists then $x will return "1". Think of it as
# <filename>_copy0.<ext>,
# this makes the file you wish to move
# <filename>_copy1.<ext>, - the value of $x.
case $x in
0) cp $filename $target
sleep .2
;;
*) mv $filename $shortname_copy$x.$ext
cp $filename $target
sleep .2
;;
esac
done
+/home/revision-6/bin/cpi:38> filename=/home/revision-6/Videos/betty_boop_a_song_a_day_1936.mkv
/home/revision-6/Videos/betty_boop_is_my_palm_read_1932.mkv
/home/revision-6/Videos/betty_boop_more_pep_1936.mkv
+/home/revision-6/bin/cpi:39> unset x
+/home/revision-6/bin/cpi:42> filename=betty_boop_more_pep_1936.mkv
+/home/revision-6/bin/cpi:43> echo
+/home/revision-6/bin/cpi:44> echo
+/home/revision-6/bin/cpi:45> echo 'filename=betty_boop_more_pep_1936.mkv'
filename=betty_boop_more_pep_1936.mkv
+/home/revision-6/bin/cpi:46> echo
+/home/revision-6/bin/cpi:47> echo
+/home/revision-6/bin/cpi:49> shortname=betty_boop_more_pep_1936
+/home/revision-6/bin/cpi:50> echo 'shortname=betty_boop_more_pep_1936'
shortname=betty_boop_more_pep_1936
+/home/revision-6/bin/cpi:51> echo
+/home/revision-6/bin/cpi:52> echo
+/home/revision-6/bin/cpi:54> ext=mkv
+/home/revision-6/bin/cpi:55> echo
+/home/revision-6/bin/cpi:56> echo
+/home/revision-6/bin/cpi:57> echo 'ext=mkv'
ext=mkv
+/home/revision-6/bin/cpi:62> x=+/home/revision-6/bin/cpi:62> find /home/revision-6/video_processing -iname 'betty_boop_more_pep_1936*.mkv'
+/home/revision-6/bin/cpi:62> x=+/home/revision-6/bin/cpi:62> wc -c
+/home/revision-6/bin/cpi:62> x=0
+/home/revision-6/bin/cpi:63> echo
+/home/revision-6/bin/cpi:64> echo
+/home/revision-6/bin/cpi:65> echo 'x=0'
x=0
+/home/revision-6/bin/cpi:73> case 0 (0)
+/home/revision-6/bin/cpi:74> cp betty_boop_more_pep_1936.mkv /home/revision-6/video_processing
+/home/revision-6/bin/cpi:75> sleep .2
exit 0
+/home/revision-6/bin/cpi:83> exit 0
revision-6@revision6-NYI3 ~/Videos
% cpi
+/home/revision-6/bin/cpi:4> setopt -v
autoload -Uz zmv
+/home/revision-6/bin/cpi:5> autoload -Uz zmv
# WARNING Just because two or more files from different sources have identical names does not mean
#that the files are identical.
declare -a array
+/home/revision-6/bin/cpi:11> declare -a array
array=$(yad --width=600 --height=800 \
--title="Choose files to move." \
--file --multiple --separator='\n')
+/home/revision-6/bin/cpi:12> array=+/home/revision-6/bin/cpi:12> yad '--width=600' '--height=800' '--title=Choose files to move.' --file --multiple '--separator=\n'
(yad:3962420): dbind-WARNING **: 15:35:35.029: Couldn't connect to accessibility bus: Failed to connect to socket /root/.cache/at-spi/bus_0.0: Permission denied
+/home/revision-6/bin/cpi:12> array=$'/home/revision-6/Videos/betty_boop_a_song_a_day_1936.mkv\n/home/revision-6/Videos/betty_boop_is_my_palm_read_1932.mkv\n/home/revision-6/Videos/betty_boop_more_pep_1936.mkv'
echo $array
+/home/revision-6/bin/cpi:15> echo $'/home/revision-6/Videos/betty_boop_a_song_a_day_1936.mkv\n/home/revision-6/Videos/betty_boop_is_my_palm_read_1932.mkv\n/home/revision-6/Videos/betty_boop_more_pep_1936.mkv'
/home/revision-6/Videos/betty_boop_a_song_a_day_1936.mkv
/home/revision-6/Videos/betty_boop_is_my_palm_read_1932.mkv
/home/revision-6/Videos/betty_boop_more_pep_1936.mkv
target=$(yad --width=600 --height=800 \
--title="Choose destination." \
--file --directory)
+/home/revision-6/bin/cpi:17> target=+/home/revision-6/bin/cpi:17> yad '--width=600' '--height=800' '--title=Choose destination.' --file --directory
(yad:3962450): dbind-WARNING **: 15:35:43.654: Couldn't connect to accessibility bus: Failed to connect to socket /root/.cache/at-spi/bus_0.0: Permission denied
+/home/revision-6/bin/cpi:17> target=/home/revision-6/video_processing
echo "target="$target
+/home/revision-6/bin/cpi:20> echo 'target=/home/revision-6/video_processing'
target=/home/revision-6/video_processing
# The file you wish to move may already exist in the target directory.
# If you do not want to overwrite it you can use
# mv -n
# mv --no-clobber
# or
# mv --backup=numbered
# Clumsy, but better than nothing, and doesn't give me what I want.
# That is why I wrote this script, it adds an incremented number to the name.
# eg <movie>.<ext>
# eg <movie>_copy1.<ext>
# eg <movie>_copy2.<ext>
# Yes, I could use brackets but they are illegal characters and I have a renamer
# that would remove them.
# You can't just use <filename>.$ext to check if the file exists in target because
# you'll miss any existing copies. You have to account for iteration.
for filename in $array; do
unset x
# decompose filename
# just name without path
filename=$filename:t
echo
echo
echo "filename="$filename
echo
echo
# name without extension
shortname=${filename%.*}
echo "shortname="$shortname
echo
echo
# extension
ext=${filename##*.}
echo
echo
echo "ext="$ext
# The key here is to rename the file (if necessary) BEFORE copying it to target instead
# of after.
# Does file already exist in $target? Count them.
x=$(find $target -iname "$shortname*.$ext" | wc -c)
echo
echo
echo "x="$x
# If no file exists, move to target.
# If one file exists then $x will return "1". Think of it as
# <filename>_copy0.<ext>,
# this makes the file you wish to move
# <filename>_copy1.<ext>, - the value of $x.
case $x in
0) cp $filename $target
sleep .2
;;
*) mv $filename $shortname_copy$x.$ext
cp $filename $target
sleep .2
;;
esac
done
+/home/revision-6/bin/cpi:38> filename=/home/revision-6/Videos/betty_boop_a_song_a_day_1936.mkv
/home/revision-6/Videos/betty_boop_is_my_palm_read_1932.mkv
/home/revision-6/Videos/betty_boop_more_pep_1936.mkv
+/home/revision-6/bin/cpi:39> unset x
+/home/revision-6/bin/cpi:42> filename=betty_boop_more_pep_1936.mkv
+/home/revision-6/bin/cpi:43> echo
+/home/revision-6/bin/cpi:44> echo
+/home/revision-6/bin/cpi:45> echo 'filename=betty_boop_more_pep_1936.mkv'
filename=betty_boop_more_pep_1936.mkv
+/home/revision-6/bin/cpi:46> echo
+/home/revision-6/bin/cpi:47> echo
+/home/revision-6/bin/cpi:49> shortname=betty_boop_more_pep_1936
+/home/revision-6/bin/cpi:50> echo 'shortname=betty_boop_more_pep_1936'
shortname=betty_boop_more_pep_1936
+/home/revision-6/bin/cpi:51> echo
+/home/revision-6/bin/cpi:52> echo
+/home/revision-6/bin/cpi:54> ext=mkv
+/home/revision-6/bin/cpi:55> echo
+/home/revision-6/bin/cpi:56> echo
+/home/revision-6/bin/cpi:57> echo 'ext=mkv'
ext=mkv
+/home/revision-6/bin/cpi:62> x=+/home/revision-6/bin/cpi:62> find /home/revision-6/video_processing -iname 'betty_boop_more_pep_1936*.mkv'
+/home/revision-6/bin/cpi:62> x=+/home/revision-6/bin/cpi:62> wc -c
+/home/revision-6/bin/cpi:62> x=63
+/home/revision-6/bin/cpi:63> echo
+/home/revision-6/bin/cpi:64> echo
+/home/revision-6/bin/cpi:65> echo 'x=63'
x=63
+/home/revision-6/bin/cpi:73> case 63 (0)
+/home/revision-6/bin/cpi:73> case 63 (*)
+/home/revision-6/bin/cpi:77> mv betty_boop_more_pep_1936.mkv 63.mkv
+/home/revision-6/bin/cpi:78> cp betty_boop_more_pep_1936.mkv /home/revision-6/video_processing
cp: cannot stat 'betty_boop_more_pep_1936.mkv': No such file or directory
+/home/revision-6/bin/cpi:79> sleep .2
exit 0
+/home/revision-6/bin/cpi:83> exit 0
在我看来,这个逻辑似乎有效。在移动文件之前,计算目标中的迭代次数并重命名文件,但我想我的 shell 脚本编写能力不足以胜任这项任务。欢迎任何帮助。