Frage Ich analysiere die Ausgabe von `ls` und etwas ging schief


Ich habe dieses einfache Skript erstellt, um eine Datei rekursiv in viele Unterverzeichnisse zu kopieren. Hier zeige ich das Problem für 3 Unterverzeichnisse. Ich habe 3 Unterverzeichnisse und 2 Dateien in einem Verzeichnis wie folgt

0.003/  0.007/  0.015/  program.cpp  driver.sh*

Ich möchte kopieren program.cpp zu all diesen Unterverzeichnissen mit myscript.sh unten gezeigt:

    #!/bin/bash
    mydir=`pwd`

    for i in `ls -la $mydir | grep "[0-9]$" | awk '{print $NF}'`
    do
        if [ -e $mydir/$1 ]
        then
            echo "cp -i $1 $i/"
        else
            echo "File \"$1\" not found in current directory"
        fi
    done

Ich habe das gestellt cp Innerhalb echo um den Code zu testen. Die Ausgabe ist seltsam,

cp -i program.cpp 32/
cp -i program.cpp 0.003/
cp -i program.cpp 0.007/
cp -i program.cpp 0.015/

Die Ausgabe von ls -la

total 32K
drwxr-xr-x. 5 gulu workg 4.0K Nov 29  2013 .
drwxr-xr-x. 7 gulu workg 4.0K Nov 29  2013 ..
drwxr-xr-x. 2 gulu workg 4.0K Nov 26 19:09 0.003
drwxr-xr-x. 2 gulu workg 4.0K Nov 26 19:09 0.007
drwxr-xr-x. 2 gulu workg 4.0K Nov 26 19:09 0.015
-rw-r--r--. 1 gulu workg 4.2K Nov 29  2013 program.cpp
-rwxr-xr-x. 1 gulu workg  982 Nov 26 08:22 driver.sh

Die Ausgabe von ls -la $mydir | grep "[0-9]$" | awk '{print $NF}'

0.003
0.007
0.015

Es gibt nur drei Werte i Wie produziert es dann vier Ausgaben? Wie auch immer, ich habe das Problem mit einer zusätzlichen Bedingung gelöst [ -d $mydir/$i ]. Aber meine Frage ist, wie das Skript die erste Zeile produziert cp -i driver.sh 32/?


1
2017-11-28 16:50


Ursprung


Sie könnten das erste "d" der Liste zuordnen. Beachten Sie, dass awk das tun kann, was grep tut: ls -la $mydir| awk '/^d.*[0-9]$/ {print $NF}' - Emmanuel
@ Emmanuel ja, es ist in der Tat ein besserer Vorschlag. Vielen Dank. - souravc


Antworten:


Dies veranschaulicht, warum Sie sich NIEMALS darauf verlassen sollten, die Ausgabe des ls Befehl, um über Verzeichnisinhalte zu iterieren - verwenden Sie stattdessen einen einfachen Shell-Glob, z. um jeden Dateinamen zu finden, der mit einer Ziffer endet

for f in $mydir/*[0-9]
do
    if [ -e $mydir/$1 ]
    .
    .
done

Wie es die Linie produziert cp -i driver.sh 32/, können Sie sehen, wenn Sie nach Ziffern in der Ausgabe von suchen ls -laes passt zu den total: 32K Zeile sowie die gewünschten Verzeichnisnamen.


4
2017-11-28 17:22



Ohh! Jetzt habe ich es, wenn Sie darauf hinweisen ls. Ich habe hier und da Fehler gefunden. Eigentlich in meinem .bashrc Ich habe einen Alias ​​für ls wie 'ls -h --color=auto'. Deshalb Ausgabe von ls -la gezeigt total 32K und gefiltert durch grep mit Feld endet mit Nummer verwerfen. Aber wenn das Skript läuft, denke ich, dass es benutzt /bin/ls und vier Werte zu nehmen, wobei die erste Zeile als gelesen wird total 32. Ich habe eine gute Lektion gelernt. Vielen dank für Deine Hilfe. - souravc


Dies veranschaulicht, warum Sie sich NIEMALS darauf verlassen sollten, die Ausgabe des Befehls ls zu analysieren, um über Verzeichnisinhalte zu iterieren - verwenden Sie ein einfaches find Befehl:

find . -maxdepth 1 -type d --regex './[0-9]+$' -exec cp $1 {} \;

1
2018-04-07 23:39