2014-06-25 10 views
5

habe ich ein Shell-Skript (test.sh) mit Java geschrieben. Dieses Shell-Skript führt tatsächlich einen Kopiervorgang von einer Datei zur anderen durch. Nach der Ausführung des Shell-Skripts habe ich das Verzeichnis von Console aus geöffnet und ls eingegeben. Es zeigt die Ausgabedatei mit? nach der Erweiterung.Unix: "ls" Befehl zeigt Dateien mit? nach der Erweiterung

Beispiel: foo.csv?

File execFile = new File(file); 
FileWriter fwFile; 
try { 
    fwFile = new FileWriter(execFile); 
    execFile.setExecutable(true); 
    BufferedWriter bwFile = new BufferedWriter(fwFile); 
    bwFile.write(strOutput.substring(0, 2)); 
    bwFile.write("\r\n"); 
    bwFile.write("cd " + strOutput); 
    bwFile.write("\r\n"); 
    bwFile.write("mkdir " + strOutput); 
    bwFile.write("\r\n"); 
    bwFile.write(strUnixPath); 
    bwFile.write("\r\n"); 
    bwFile.write("cd " + strWorkingPath + IPlatinumConstants.FS+"lib"+IPlatinumConstants.FS+"Unx"); 
    bwFile.write("\r\n"); 
    bwFile.write("echo Cut Src Start time %time%"); 
    bwFile.write("\r\n"); 

      bwFile.write("cp " + " \"" + strSourceFilePath + "\" \"" 
        + strOutput + "copy_A\""); 
      bwFile.write("\r\n"); 
+0

'ls' sollte ** nie ** für Endverbraucher zu anderen Zwecken als zur Anzeige * verwendet werden, nur für den menschlichen Verzehr *. Lesen Sie http://mywiki.wooledge.org/ParsingLs für eine Beschreibung von (nur einigen) Dingen, die schief gehen können, indem Sie 'ls' programmatisch verwenden. –

+0

Ihr Programm hat auch Shell-Injection-Sicherheitsfehler, wie sie gerade geschrieben werden - wenn ein Verzeichnis einen Namen wie 'foo $ (rm -rf $ HOME) bar 'hat, erraten Sie, was passiert, wenn Sie eine Shell gegen den Puffer aufrufen, in den Sie geschrieben haben ? –

Antwort

13

Meine Vermutung:

Ihr Java-Programm wird mit \r\n, Wagenrücklauf + Zeilenvorschub, jede Zeile zu beenden. Unix-Systeme verwenden jedoch nur den Zeilenvorschub \n als eine neue Zeile Indikator. Während der Wagenrücklauf von Terminals verstanden wird, hat es keine Bedeutung für andere Programme – es ist nur ein Zeichen wie jeder andere, soweit der   /bin/sh Interpreter betroffen ist. Dies bedeutet, dass die \r Teil des letzten Parameters jeden Befehl, der das Skript ausgeführt wird:

cd myoutput\r 
mkdir myoutput\r 
cd something/lib/something\r 
echo Cut Src Start time %time%\r 
cp "sourcefile" "myoutputcopy_A"\r 

So ist der letzte Befehl immer Erstellen von Dateien, die den Wagenrücklauf am Ende ihres Namen haben und   ls zeigt sie als Fragezeichen wie alle anderen "nicht druckbaren" Zeichen. Sie können dies unter Verwendung von   ls -b oder   ls -Q sehen.

Um dies zu beheben, verwenden Sie nur \n beim Generieren von Unix-Shell-Skripten. (Oder, noch besser, nicht generieren Shell-Skripte – stattdessen schreiben Skripte, die Parameter akzeptieren, wo erforderlich. Sie könnten viele Dinge in das Java-Programm selbst auch tun.)

+0

Ich würde tatsächlich davon ausgehen, dass das Skript nicht einmal "cd", wo das OP es wollte gehen. Also, ziemlich durcheinander. – slhck

+2

Es war wahrscheinlich _would_, wenn das 'cd' war _after_' mkdir' ... – grawity

+0

Um zu überprüfen, ob diese Antwort das eigentliche Problem widerspiegelt, kann OP 'ls | xxd' und sehen, ob nach der hexadezimalen Darstellung des Dateinamens '0d' steht. – Ruslan