Bash-脚本:在脚本中使用查找和移动无法正常工作
Bash-Scripting: Using find and move inside a script does not work properly
不幸的是,我 运行 在编写 bash 脚本时遇到了问题。
我想要实现的是:
- 我想创建一个脚本,将一些用户输入作为关键字/搜索词。
- 脚本应该使用
find
来搜索用户输入并用 print
显示它。
- 如果用户满意,应命令脚本将这些文件移动到使用
find "$searchpath" -iname "$findword" -type f -exec mv {} "$destinationpath/$season" \;
移动这些文件的目标文件夹。
这就是我的脚本的样子。注意这里有一个 NOOB 正在编写脚本!
cat find_and_move.sh
#!/bin/bash
#keyword
#searchpath
#Smin
#Smax
#season
#destinationpath
#findword
#allfine
while getopts "k:p:d:n:m:x" opt; do
case $opt in
k)
keyword=$OPTARG ;;
#get one keyword
p)
searchpath=$OPTARG ;;
#get searchpath ( where to find the keyword )
n)
Smin="$(printf '%d' $OPTARG 2>/dev/null)" ;;
#convert string to number and save as Smin
m)
Smax="$(printf '%d' $OPTARG 2>/dev/null)" ;;
#convert string to number and save as Smax
d)
destinationpath=$OPTARG ;;
#get destinationpath to copy to
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1 ;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1 ;;
esac
done
#Check if all parameters are set.
if [ -z "$keyword" ]; then echo "keyword is NULL";
else if [ -z "$searchpath" ]; then echo "searchpath is NULL";
else if [ -z "$Smin" ]; then echo "Smin is NULL";
else if [ -z "$Smax" ]; then echo "Smax is NULL";
else if [ -z "$destinationpath" ]; then echo "Destinationpath is NULL";
else echo "ALL PARAMETERS SET";
allfine="true";
fi
fi
fi
fi
fi
#MAIN: Find and print the result
if [ -z $allfine ]; then echo "allfine is NULL";
else if [ $allfine = "true" ]; then echo "Allfine = true"
while [ $Smin -le $Smax ]
do
if [ $Smin -le $Smax ] ;
then season="S0$Smin"
else season="S$Smin"
fi
findword="*$keyword*$season*"
echo $findword
echo find $searchpath -iname $findword -type f -print
find "$searchpath" -iname "$findword" -type f -print
# this search with find works properly
echo "find $searchpath -iname $findword -type f -exec mv {} $destinationpath/$season \;"
#find "$searchpath -iname $findword -type f -exec {} $destinationpath/$season \;"
let Smin++
sleep 2;
done;
#If user is satisfied with the result of find&print then order the script to move the files.
echo "Do you really want to move the files?"
read -p "" -n 1 -r
echo # (optional) move to a new line
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
exit 1
fi
echo "Files will be moved now."
sleep 2;
while [ $Smin -le $Smax ]
do
if [ $Smin -le $Smax ] ;
then season="S0$Smin"
else season="S$Smin"
fi
findword="*$keyword*$season*"
echo $findword
echo find $searchpath -iname $findword -type f -print
find $searchpath -iname $findword -type f -print
#this find search with print works properly
echo "find $searchpath -iname $findword -type f -exec mv {} $destinationpath/$season \;"
#the output of echo is correct and works using copy and paste in terminal
find "$searchpath" -iname "$findword" -type f -exec mv {} "$destinationpath/$season" \;
#this find -exec mv command seems to be ignored. No error is shown.
let Smin++
sleep 2;
done;
exit 1
fi
fi
当我用 ./find_and_move.sh -k mykeyword -p mysearchpath -d destinationfolder -n low-number -m high-number
调用该脚本时,一切正常,只是它不移动文件。我也没有收到任何错误消息。
当我将 echo "find $searchpath -iname $findword -type f -exec mv {} $destinationpath/$season \;"
的结果复制并粘贴到终端时,文件的移动没有问题。没有 echo
命令似乎被忽略(检查我在脚本中的最后三个评论)。
编辑 4 月 26 日
我在你的脚本里修改了很多东西,你看看:
#!/bin/bash
usage()
{
echo ""
echo "Usage: [=10=] -k <keyword> -p <search path> -d <destination folder> -n <value> -m <value>"
exit 1
}
while getopts "k:p:d:n:m:x" opt
do
case $opt in
k)
#get one keyword
keyword="$OPTARG"
;;
p)
#get searchpath ( where to find the keyword )
searchpath="$OPTARG"
;;
n)
#convert string to number and save as Smin
Smin="$OPTARG"
;;
m)
#convert string to number and save as Smax
Smax="$OPTARG"
;;
d)
#get destinationpath to copy to
destinationpath="$OPTARG"
;;
\?)
echo "Invalid option: -$OPTARG" >&2
usage
;;
*)
echo "Option -$OPTARG requires an argument." >&2
usage
;;
esac
done
#Check if all parameters are set.
if [ -z "$keyword" ]
then
echo "keyword is NULL"
usage
elif [ -z "$searchpath" ]
then
echo "searchpath is NULL"
usage
elif [ -z "$Smin" ]
then
echo "Smin is NULL"
usage
elif [ -z "$Smax" ]
then
echo "Smax is NULL"
usage
elif [ -z "$destinationpath" ]
then
echo "destinationpath is NULL"
usage
fi
#DEBUG
echo "keyword=$keyword"
echo "searchpath=$searchpath"
echo "Smin=$Smin"
echo "Smax=$Smax"
echo "destinationpath=$destinationpath"
#MAIN: Find and print the result
whilemin1="$Smin"
while [[ "$whilemin1" -le "$Smax" ]]
do
echo ""
season="S0$whilemin1"
findword="*$keyword*$season*"
echo "findword=$findword"
echo "Running: find \"$searchpath\" -iname \"$findword\" -type f -print"
find "$searchpath" -iname "$findword" -type f -print
(( whilemin1++ ))
sleep 2
done
#If user is satisfied with the result of find&print then order the script to move the files.
echo ""
read -p "Do you really want to move the files? " -n 1 -r
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
echo -e "\nNo files moved."
#exit 1
else
echo -e "\nFiles will be moved now."
sleep 2
fi
whilemin2="$Smin"
while [[ "$whilemin2" -le "$Smax" ]]
do
echo ""
season="S0$whilemin2"
findword="*$keyword*$season*"
echo "findword=$findword"
echo "Running: find \"$searchpath\" -iname \"$findword\" -type f -exec mv -t \"./$destinationpath/$season\" {} +"
find "$searchpath" -iname "$findword" -type f -exec mv -t "./$destinationpath/$season" {} +
(( whilemin2++ ))
sleep 2
done
- 恕我直言,您应该将脚本命名为
find_and_move.bash
,因为您的 #!
行是 bash.
- 缩进整个代码,使代码块更容易看到。
- 删除了你所有的
;
,不需要。
- 创建了一个
usage
函数,因为在很多情况下您想要退出命令语法问题。
- 不需要
printf
将选项值转换为数字,bash 并不关心。如果您对变量值使用数字运算符,它会为您处理。
- 一起删除了
allfine
概念,如果任何参数为空,脚本仍然存在。
- 删除了您的
if then else if then else if ...
并改用 if then elif else fi
。更易于阅读。
- 在您的第一个
while
中,您有两个 find
命令。又是第二个。我把 find ... -print
放在第一个 while
,find ... -exec ...
在第二个
- 删除了
while
语句中的 if [ $Smin -le $Smax ]
。反正这个条件不成立是不可能进入while
的,何必再检查
- 对于
read
,之前不需要echo
,只需将问题作为参数传递给read
。
- 删除了旧的
let
命令,替换为 (( ))
语法。
- 运行 通过站点 https://www.shellcheck.net/ 的代码以确保没有语法问题。
我测试了我认为您希望脚本执行的操作。但是由于你没有提供完整的测试目录和文件结构,可能我没有测试到合适的东西。
注意:评论中关于通过将文件名存储在数组中来避免循环两次的建议是非常正确的,但我不想跳入那个。如果您的文件数量很少并且文件系统更改很少,那么您的脚本将起作用。 YMMV.
编辑说明:它不起作用的原因是第一个 while
增加了 Smin
,因此第二个 while
使用那个增加值,因此它永远不会进入 while
循环。修改后的版本现在为每个 while
条件使用新变量。
编辑说明 2:find
已修改以避免“文件...已存在”错误消息。 ... -exec mv -t "./$destinationpath/$season" {} +
不幸的是,我 运行 在编写 bash 脚本时遇到了问题。
我想要实现的是:
- 我想创建一个脚本,将一些用户输入作为关键字/搜索词。
- 脚本应该使用
find
来搜索用户输入并用print
显示它。 - 如果用户满意,应命令脚本将这些文件移动到使用
find "$searchpath" -iname "$findword" -type f -exec mv {} "$destinationpath/$season" \;
移动这些文件的目标文件夹。
这就是我的脚本的样子。注意这里有一个 NOOB 正在编写脚本!
cat find_and_move.sh
#!/bin/bash
#keyword
#searchpath
#Smin
#Smax
#season
#destinationpath
#findword
#allfine
while getopts "k:p:d:n:m:x" opt; do
case $opt in
k)
keyword=$OPTARG ;;
#get one keyword
p)
searchpath=$OPTARG ;;
#get searchpath ( where to find the keyword )
n)
Smin="$(printf '%d' $OPTARG 2>/dev/null)" ;;
#convert string to number and save as Smin
m)
Smax="$(printf '%d' $OPTARG 2>/dev/null)" ;;
#convert string to number and save as Smax
d)
destinationpath=$OPTARG ;;
#get destinationpath to copy to
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1 ;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1 ;;
esac
done
#Check if all parameters are set.
if [ -z "$keyword" ]; then echo "keyword is NULL";
else if [ -z "$searchpath" ]; then echo "searchpath is NULL";
else if [ -z "$Smin" ]; then echo "Smin is NULL";
else if [ -z "$Smax" ]; then echo "Smax is NULL";
else if [ -z "$destinationpath" ]; then echo "Destinationpath is NULL";
else echo "ALL PARAMETERS SET";
allfine="true";
fi
fi
fi
fi
fi
#MAIN: Find and print the result
if [ -z $allfine ]; then echo "allfine is NULL";
else if [ $allfine = "true" ]; then echo "Allfine = true"
while [ $Smin -le $Smax ]
do
if [ $Smin -le $Smax ] ;
then season="S0$Smin"
else season="S$Smin"
fi
findword="*$keyword*$season*"
echo $findword
echo find $searchpath -iname $findword -type f -print
find "$searchpath" -iname "$findword" -type f -print
# this search with find works properly
echo "find $searchpath -iname $findword -type f -exec mv {} $destinationpath/$season \;"
#find "$searchpath -iname $findword -type f -exec {} $destinationpath/$season \;"
let Smin++
sleep 2;
done;
#If user is satisfied with the result of find&print then order the script to move the files.
echo "Do you really want to move the files?"
read -p "" -n 1 -r
echo # (optional) move to a new line
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
exit 1
fi
echo "Files will be moved now."
sleep 2;
while [ $Smin -le $Smax ]
do
if [ $Smin -le $Smax ] ;
then season="S0$Smin"
else season="S$Smin"
fi
findword="*$keyword*$season*"
echo $findword
echo find $searchpath -iname $findword -type f -print
find $searchpath -iname $findword -type f -print
#this find search with print works properly
echo "find $searchpath -iname $findword -type f -exec mv {} $destinationpath/$season \;"
#the output of echo is correct and works using copy and paste in terminal
find "$searchpath" -iname "$findword" -type f -exec mv {} "$destinationpath/$season" \;
#this find -exec mv command seems to be ignored. No error is shown.
let Smin++
sleep 2;
done;
exit 1
fi
fi
当我用 ./find_and_move.sh -k mykeyword -p mysearchpath -d destinationfolder -n low-number -m high-number
调用该脚本时,一切正常,只是它不移动文件。我也没有收到任何错误消息。
当我将 echo "find $searchpath -iname $findword -type f -exec mv {} $destinationpath/$season \;"
的结果复制并粘贴到终端时,文件的移动没有问题。没有 echo
命令似乎被忽略(检查我在脚本中的最后三个评论)。
编辑 4 月 26 日
我在你的脚本里修改了很多东西,你看看:
#!/bin/bash
usage()
{
echo ""
echo "Usage: [=10=] -k <keyword> -p <search path> -d <destination folder> -n <value> -m <value>"
exit 1
}
while getopts "k:p:d:n:m:x" opt
do
case $opt in
k)
#get one keyword
keyword="$OPTARG"
;;
p)
#get searchpath ( where to find the keyword )
searchpath="$OPTARG"
;;
n)
#convert string to number and save as Smin
Smin="$OPTARG"
;;
m)
#convert string to number and save as Smax
Smax="$OPTARG"
;;
d)
#get destinationpath to copy to
destinationpath="$OPTARG"
;;
\?)
echo "Invalid option: -$OPTARG" >&2
usage
;;
*)
echo "Option -$OPTARG requires an argument." >&2
usage
;;
esac
done
#Check if all parameters are set.
if [ -z "$keyword" ]
then
echo "keyword is NULL"
usage
elif [ -z "$searchpath" ]
then
echo "searchpath is NULL"
usage
elif [ -z "$Smin" ]
then
echo "Smin is NULL"
usage
elif [ -z "$Smax" ]
then
echo "Smax is NULL"
usage
elif [ -z "$destinationpath" ]
then
echo "destinationpath is NULL"
usage
fi
#DEBUG
echo "keyword=$keyword"
echo "searchpath=$searchpath"
echo "Smin=$Smin"
echo "Smax=$Smax"
echo "destinationpath=$destinationpath"
#MAIN: Find and print the result
whilemin1="$Smin"
while [[ "$whilemin1" -le "$Smax" ]]
do
echo ""
season="S0$whilemin1"
findword="*$keyword*$season*"
echo "findword=$findword"
echo "Running: find \"$searchpath\" -iname \"$findword\" -type f -print"
find "$searchpath" -iname "$findword" -type f -print
(( whilemin1++ ))
sleep 2
done
#If user is satisfied with the result of find&print then order the script to move the files.
echo ""
read -p "Do you really want to move the files? " -n 1 -r
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
echo -e "\nNo files moved."
#exit 1
else
echo -e "\nFiles will be moved now."
sleep 2
fi
whilemin2="$Smin"
while [[ "$whilemin2" -le "$Smax" ]]
do
echo ""
season="S0$whilemin2"
findword="*$keyword*$season*"
echo "findword=$findword"
echo "Running: find \"$searchpath\" -iname \"$findword\" -type f -exec mv -t \"./$destinationpath/$season\" {} +"
find "$searchpath" -iname "$findword" -type f -exec mv -t "./$destinationpath/$season" {} +
(( whilemin2++ ))
sleep 2
done
- 恕我直言,您应该将脚本命名为
find_and_move.bash
,因为您的#!
行是 bash. - 缩进整个代码,使代码块更容易看到。
- 删除了你所有的
;
,不需要。 - 创建了一个
usage
函数,因为在很多情况下您想要退出命令语法问题。 - 不需要
printf
将选项值转换为数字,bash 并不关心。如果您对变量值使用数字运算符,它会为您处理。 - 一起删除了
allfine
概念,如果任何参数为空,脚本仍然存在。 - 删除了您的
if then else if then else if ...
并改用if then elif else fi
。更易于阅读。 - 在您的第一个
while
中,您有两个find
命令。又是第二个。我把find ... -print
放在第一个while
,find ... -exec ...
在第二个 - 删除了
while
语句中的if [ $Smin -le $Smax ]
。反正这个条件不成立是不可能进入while
的,何必再检查 - 对于
read
,之前不需要echo
,只需将问题作为参数传递给read
。 - 删除了旧的
let
命令,替换为(( ))
语法。 - 运行 通过站点 https://www.shellcheck.net/ 的代码以确保没有语法问题。
我测试了我认为您希望脚本执行的操作。但是由于你没有提供完整的测试目录和文件结构,可能我没有测试到合适的东西。
注意:评论中关于通过将文件名存储在数组中来避免循环两次的建议是非常正确的,但我不想跳入那个。如果您的文件数量很少并且文件系统更改很少,那么您的脚本将起作用。 YMMV.
编辑说明:它不起作用的原因是第一个 while
增加了 Smin
,因此第二个 while
使用那个增加值,因此它永远不会进入 while
循环。修改后的版本现在为每个 while
条件使用新变量。
编辑说明 2:find
已修改以避免“文件...已存在”错误消息。 ... -exec mv -t "./$destinationpath/$season" {} +