2017-02-27 5 views
0

この問題があるようです。このコードは、私のスクリプトのbash連想配列の119行目で壊れています。コメントは申し訳なく思っていますが、私はbashスクリプティングには新しく親切です。これはコードです: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解決済み)どちらの名前が忘れていたのは簡単な間違いでした。

+2

これを*最小*の例にする必要があります。あなたが投稿したコードのほとんどはあなたの問題とは無関係です。 – chepner

+0

スクリプトを起動するには、コマンドラインを置くことができますか?とにかく、@chepnerが正しいです、必要最小限の表現に減らそう! – OscarAkaElvis

+1

そして実際には、「wall」というメッセージが表示されますか?システムの他のユーザーは、1人があなたのスクリプトをいかに悪用したかについて聞いていないでしょう。 – chepner

答えて

0

あなたの宣言がされています。しかし、あなたの使い方がある

typeset -A filelist 

fileslist["$dirFrom"]="$dirTo" 

fileslistfilelistではありません。

+0

私はとても馬鹿だと感じます。私はそれを見るにはあまりにも疲れていたと思う。ダム。それを見ていただきありがとうございます。ところで、 "$ @"では "$ *"の代わりにgetoptを使用できますか? – corax

+0

はい、 'getopt'は実際には悪い習慣です。堅牢な代替案については、[BashFAQ#35](http://mywiki.wooledge.org/BashFAQ/035)を参照してください。おかげさまで –

+0

ありがとうございます。今すぐリンクを見てください。 – corax