Das macht David traurig ...
Jeder ist bisher falsch (außer anubhava ).
Shell-Scripting ist nicht wie jede andere Programmiersprache, da ein großer Teil der Zeileninterpretation von der Stärke der Shell herrührt, die sie interpoliert, bevor der Befehl tatsächlich ausgeführt wird.
Nehmen wir etwas Einfaches:
%Vor% Mit set -x
können Sie sehen, wie die Shell den Glob interpoliert und diesen dann als Eingabe an den Befehl zurückgibt. % Co_de% zeigt auf die Zeile, die tatsächlich vom Befehl ausgeführt wird.
Sie können sehen, dass der Befehl >
das echo
nicht interpretiert. Stattdessen greift die Shell auf *
und ersetzt sie durch die Namen der übereinstimmenden Dateien. Dann und nur dann führt der Befehl *
den Befehl tatsächlich aus.
Wenn Sie 40K plus Dateien haben und echo
, dann erweitern Sie das grep *
auf die Namen dieser 40.000 plus Dateien, bevor *
sogar eine Chance hat, ausgeführt zu werden, und das ist die Fehlermeldung / usr / bin / grep: Zu lange Argumentliste kommt von.
Glücklicherweise hat Unix einen Weg um dieses Dilemma zu umgehen:
%Vor% Das grep
findet alle find . -name "*.kaks" -type f -maxdepth 1
Dateien und das *.kaks
nur die Dateien im aktuellen Verzeichnis. Der -depth 1
stellt sicher, dass Sie nur Dateien und kein Verzeichnis auswählen.
Der Befehl -type f
leitet die Namen der Dateien in find
und xargs
fügt die Namen der Datei an den Befehl xargs
an. % Co_de% hat jedoch einen Trick im Ärmel. Er weiß, wie lange der Befehlszeilenpuffer ist, und führt den grep -f A01/genes.txt
aus, wenn der Befehlszeilenpuffer voll ist, und übergibt dann eine weitere Reihe von Dateien an den xargs
. Auf diese Weise wird grep
möglicherweise drei- oder zehnmal ausgeführt (abhängig von der Größe des Befehlszeilenpuffers) und alle unsere Dateien werden verwendet.
Leider verwendet grep
Whitespace als Trennzeichen für die Dateinamen. Wenn Ihre Dateien Leerzeichen oder Tabulatoren enthalten, haben Sie Probleme mit grep
. Glücklicherweise gibt es eine andere Lösung:
Das xargs
bewirkt, dass xargs
die Namen der Dateien ausdruckt, die nicht durch Zeilenumbrüche getrennt sind, sondern durch das NUL-Zeichen. Der -print0
-Parameter für find
sagt -0
, dass das Dateitrennzeichen nicht Leerzeichen ist, sondern das NUL-Zeichen. So behebt das Problem.
Sie könnten das auch tun:
%Vor% Dies führt die xargs
für jede gefundene Datei aus, anstatt xargs
und führt nur grep
für alle Dateien aus, die in der Befehlszeile eingefügt werden können. Der Vorteil davon ist, dass es die Schaleninterferenz vollständig vermeidet. Es ist jedoch möglicherweise nicht weniger effizient.
Was interessant wäre, ist zu experimentieren und zu sehen, welches effizienter ist. Sie können xargs
verwenden, um Folgendes anzuzeigen:
Dies wird den Befehl ausführen und Ihnen dann sagen, wie lange es gedauert hat. Probieren Sie es mit dem grep
und mit time
aus und sehen Sie, welches schneller ist. Lass uns wissen, was du findest.
Setzen Sie eine andere Schleife in Ihre äußere:
%Vor%Übrigens, sind Sie daran interessiert, JEDES Vorkommnis in jeder Datei zu finden oder nur, wenn die Suchzeichenfolge einmal oder mehrmals dort existiert? Wenn es "gut genug" ist zu wissen, dass die Zeichenkette dort ein- oder mehrmals vorkommt, können Sie "-n 1" für grep angeben, und es wird nicht den Rest der Datei nach dem Finden der ersten Übereinstimmung lesen / durchsuchen, was möglicherweise Sparen Sie viel Zeit.