【发布时间】:2017-07-18 16:57:33
【问题描述】:
我好像有这个问题。此代码在我的脚本的第 119 行使用 bash 关联数组中断。我为 cmets 感到抱歉,但我很喜欢 bash 脚本的新手。这是代码:
#!/bin/bash
# Aliases file
# Command usage: cpRecent/mvRecent -d {dirFrom},{dirTo} -n {numberofFiles} -e {editTheNames}
# Error codes
NO_ARGS="You need to pass in an argument"
INVALID_OPTION="Invaild option:"
NO_DIRECTORY="No directory found"
# Return values
fullpath=
directories=
numfiles=
interactive=
typeset -a files
typeset -A filelist
# Advise that you use relative paths
__returnFullPath(){
local npath
if [[ -d $1 ]]; then
cd "$(dirname $1)"
npath="$PWD/$(basename $1)"
npath="$npath/" #Add a slash
npath="${npath%.*}" #Delete .
fi
fullpath=${npath:=""}
}
__usage(){
wall <<End-Of-Message
________________________________________________
<cpRecent/mvRecent> -d "<d1>,<d2>" -n <num> [-i]
-d First flag: Takes two arguments
-n Second flag: Takes one argument
-i Takes no arguments. Interactive mode
d1 Directory we are reading from
d2 Directory we are writing to
num Number of files
________________________________________________
End-Of-Message
}
__processOptions(){
while getopts ":d:n:i" opt; do
case $opt in
d ) IFS=',' read -r -a directories <<< "$OPTARG";;
n ) numfiles=$OPTARG;;
i ) interactive=1;;
\? ) echo "$INVALID_OPTION -$OPTARG" >&2 ; return 1;;
: ) echo "$NO_ARGS"; __usage; return 1;;
* ) __usage; return 1;;
esac
done
}
__getRecentFiles(){
# Check some conditions
(( ${#directories[@]} != 2 )) && echo "$INVALID_OPTION Number of directories must be 2" && return 2
#echo ${directories[0]} ${directories[1]}
# Get the full paths of the directories to be read from/written to
__returnFullPath "${directories[0]}"
directories[0]="$fullpath"
__returnFullPath "${directories[1]}"
directories[1]="$fullpath"
if [[ -z ${directories[0]} || -z ${directories[1]} ]]; then
echo $NO_DIRECTORY
return 3
fi
[[ numfiles != *[!0-9]* ]] && echo "$INVALID_OPTION Number of files cannot be a string" && return 4
#numfiles=$(($numfiles + 0))
(( $numfiles == 0 )) && echo "$INVALID_OPTION Number of files cannot be zero" && return 4
local num="-"$numfiles""
# Get the requested files in directory(skips directories)
if [[ -n "$(ls -t ${directories[0]} | head $num)" ]]; then
# For some reason using local -a or declare -a does not seem to split the string into two
local tempfiles=($(ls -t ${directories[0]} | head $num))
#IFS=' ' read -r -a tempfiles <<< "$string"
#echo ${tempfiles[@]}
for index in "${!tempfiles[@]}"; do
echo $index ${tempfiles[index]}
[[ -f "${directories[0]}${tempfiles[index]}" ]] && files+=("${tempfiles[index]}")
done
fi
}
####################################
# The problem is this piece of code
__processLines(){
local name
local answer
local dirFrom
local dirTo
if [[ -n $interactive ]]; then
for (( i=0; i< ${#files[@]}; i++ )); do
name=${files[i]}
read -n 1 -p "Old name: $name. Do you wish to change the name(y/n)?" answer
[[ answer="y" ]] && read -p "Enter new name:" name
dirFrom="${directories[0]}${files[i]}"
dirTo="${directories[1]}$name"
fileslist["$dirFrom"]="$dirTo"
done
else
for line in $files; do
dirFrom="${directories[0]}$line"
echo $dirFrom # => /home/reclusiarch/Documents/test
dirTo="${directories[1]}$line"
echo $dirTo # => /home/reclusiarch/test
fileslist["$dirFrom"]="$dirTo" # This is the offending line
done
fi
}
###########################################################
cpRecent(){
__processOptions $*
__getRecentFiles
__processLines
for line in "${!filelist[@]}"; do
cp $line ${filelist[$line]}
done
echo "You have copied ${#fileList[@]} files"
unset files
unset filelist
return
}
mvRecent(){
__processOptions $*
__getRecentFiles
__processLines
for line in "${!filelist[@]}"; do
mv $line ${filelist[$line]}
done
echo "You have copied ${#fileList[@]} files"
unset files
unset filelist
return
}
cpRecent "$*"
我已经尝试了很多东西。要运行脚本,
$ bash -x ./testing.sh -d "Documents,." -n 2
但似乎没有任何效果: 错误是这样的(使用 bash -x 时):
./testing.sh: line 119: /home/reclusiarch/Documents/test: syntax error: operand expected (error token is "/home/reclusiarch/Documents/test")
如果我在命令行上运行该部分,它可以工作:
$ typeset -A filelist
$ filelist["/home/reclusiarch/Documents/test"]=/home/reclusiarch/test
$ echo ${filelist["/home/reclusiarch/Documents/test"]}
/home/reclusiarch/test
感谢您的帮助!!
编辑:我最初将脚本缩减为一段有问题的代码,但这可能使其无法运行。同样,如果你想测试它,你可以运行给定的 bash 命令。 (理想情况下,该脚本将驻留在用户的 $HOME 目录中)。
编辑:已解决(Charles Duffy 已解决)这是一个简单的错误,忘记了哪个名字是哪个。
【问题讨论】:
-
您需要将其缩减为最小示例;您发布的大部分代码与您的问题无关。
-
你如何启动你的脚本,你能放命令行吗?不管怎样,@chepner 是对的,尽量减少到最低限度的表达!
-
真的,
wall显示使用信息?系统的其他用户不会喜欢听到有人如何滥用您的脚本。 -
@chepner 我已经削减了它。但其他代码片段使脚本能够运行。我也不妨加进去。
-
顺便说一句,使用
$*(将您的所有条目组合成一个大字符串,破坏有关其原始边界的信息)是一种代码味道——通常,正确的方式使用"$@"传递或处理任何数组都保持其元素不同。考虑习惯性地使用shellcheck.net。
标签: bash shell associative-array