2017-02-27 6 views
0

ich scheinen dieses Problem zu haben. Dieser Code bricht in Zeile 119 in meinem Skript mit bash-assoziativen Arrays. Es tut mir leid für die Kommentare, aber ich bin nett zu Bash Scripting. Dies ist der Code:Bash assoziative Arrays Fehler

#!/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 "$*" 

Ich habe eine Menge Dinge ausprobiert. Um das Skript auszuführen,

$ bash -x ./testing.sh -d "Documents,." -n 2 

Aber nichts scheint zu funktionieren: Der Fehler ist dies (bei Verwendung von bash -x):

./testing.sh: line 119: /home/reclusiarch/Documents/test: syntax error: operand expected (error token is "/home/reclusiarch/Documents/test") 

Wenn ich diesen Abschnitt auf der Kommandozeile ausgeführt werden, es funktioniert :

$ typeset -A filelist 
$ filelist["/home/reclusiarch/Documents/test"]=/home/reclusiarch/test 
$ echo ${filelist["/home/reclusiarch/Documents/test"]} 
/home/reclusiarch/test 

Danke für Ihre Hilfe !!

Edit: ich das Drehbuch zu dem Stück problematischen Code intially abgespeckte aber das könnte es nicht laufen lassen. Wenn Sie es erneut testen möchten, können Sie den angegebenen bash-Befehl ausführen. (Das Skript befindet sich idealerweise im Verzeichnis $ HOME des Benutzers).

Edit: Gelöst (Charles Duffy es gelöst) Es war ein einfacher Fehler des Vergessens, der Name war dem.

+2

Sie müssen dies * Beispiel auf ein Minimum * abspecken; Der Großteil des von Ihnen geposteten Codes ist für Ihr Problem irrelevant. – chepner

+0

Wie starten Sie Ihr Skript, können Sie die Befehlszeile setzen? Wie auch immer, @chepner hat recht, versuche auf den minimal benötigten Ausdruck zu reduzieren! – OscarAkaElvis

+1

Und wirklich, "Wand", um die Verwendungsnachricht anzuzeigen? Andere Benutzer des Systems werden es nicht schätzen zu hören, wie eine Person Ihr Skript missbraucht hat. – chepner

Antwort

0

Ihre Erklärung ist:

typeset -A filelist 

jedoch Ihre Nutzung ist:

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

fileslist nicht filelist ist.

+0

Ich fühle mich so dumm. Ich glaube, ich war zu müde, um es anzusehen. Damm. Danke, dass du es gesehen hast. Übrigens, würde "$ @" mir erlauben, getopt anstelle von "$ *" zu benutzen? – corax

+0

Ja, aber 'getopt' ist eigentlich eine schlechte Übung. Siehe [BashFAQ # 35] (http://mywiki.wooled.org/BashFAQ/035) für robuste Alternativen. –

+0

Danke. Den Link jetzt ansehen. – corax