Befehl für einzelne Datei ausführen, wenn sie mit einer Shell-Magie geändert wurde (z. B. Erweiterung ersetzen)

687
Hotschke

Ich schreibe mehrere .gv- Dateien ( graphviz ) im selben Verzeichnis und möchte neatosofort eine PNG-Datei erstellen, wenn ich eine davon gespeichert habe. Ich befinde mich unter macOS 10.12.6 mit zshmeiner Standard-Shell und habe entrvon http://entrproject.org/ installiert, um Dateiänderungen zu überwachen. Ich habe den Befehl ohne Glück versucht

$ echo $0 -zsh $ ls *.gv | entr 'F="/_";neato -Tpng "$F" -o"$"' entr: exec F="/_";neato -Tpng "$F" -o"$": No such file or directory 

Folgende Arbeiten

  1. Einfaches Drucken der zuletzt geänderten Datei

    $ ls *.gv | entr echo /_ # Press <Space> to manually trigger event to see last changed file /Users/hotschke/complete.gv 
  2. Verwenden Sie den gleichen Ausgabenamen für alle Dateien:

    $ ls *.gv | entr neato -Tpng /_ -oConstantname.png 
  3. Ersetzen Sie .gv durch .png

    $ F="/Users/hotschke/complete.gv";neato -Tpng "$F" -o"$" 

Beachten Sie das spezielle Argument /_vonentr

Das spezielle /_Argument (etwas analog zu $_Perl) bietet eine schnelle Möglichkeit, auf die erste geänderte Datei zu verweisen. Wenn eine einzelne Datei aufgeführt ist, ist dies eine praktische Methode, um zu vermeiden, dass ein Pfadname zweimal eingegeben wird:

Es wäre toll, mehrere Antworten mit verschiedenen Werkzeugen (zB Wächter, Watchdog, fswatch, ENTR, launchd (mac-only), siehe auch die Diskussion haben https://stackoverflow.com/q/1515730/ )

1
Verwenden Sie "inotifywait -m", das die berührten Knoten ausgibt, und nicht "enter", das eine Liste der zu überwachenden Knoten zu verbrauchen scheint. Sie können dann `sed` (oder ähnliches) verwenden, um einen Befehl zum Ausführen auszuführen. Attie vor 6 Jahren 0
Ich habe nichts dagegen, inotifywait zu verwenden. Soweit ich sehen kann, existiert es unter macOS jedoch nicht. Hotschke vor 6 Jahren 0
Ich würde eine plattformübergreifende Lösung vorziehen, aber es ist so gut, nur eingebaute Dienstprogramme zu verwenden. Hotschke vor 6 Jahren 0
Du hast das `inotify'-Tag benutzt ... Attie vor 6 Jahren 0
Attie: Sorry für den irreführenden Tag! Ich habe keinen guten gefunden. Hotschke vor 6 Jahren 0
Haben Sie [fswatch] (https://github.com/emcrisostomo/fswatch) gesehen? Attie vor 6 Jahren 0
@bertieb: Dies ist der letzte Schritt, wenn Sie den 2. und 3. Befehl kombinieren: Ersetzen Sie den Namen der konstanten Ausgabedatei durch den von `/ _` abgeleiteten, indem Sie die Erweiterung` gv` durch `png` ersetzen. Ich denke, es ist möglicherweise eine Frage der Muschelflucht. Funktioniert mein eingangs erwähnter Befehl für Sie? Ich wäre überrascht Hotschke vor 6 Jahren 0
@bertieb: Ich habe der Frage auch die Fehlermeldung hinzugefügt. Hotschke vor 6 Jahren 0
@Hotschke Sieht so aus, als wären wir beide bis zum Bitbucket-Repo gekommen. Möchten Sie die Erklärung von Eic als Antwort hinzufügen? Ich bin froh, die Schleife zu schließen, aber ich dachte, du solltest den ersten Crack bekommen :) bertieb vor 6 Jahren 0

4 Antworten auf die Frage

2
bertieb

Rufen Sie ein Skript mit auf entr

tl; dr : /_als Argument an ein Skript an Do The Thing ™ übergeben

Anstatt zu versuchen, sich mit speziellen Argumenten und Variablen zu beschäftigen, sollten Sie /_zu einem einfachen Skript wechseln (das selbst ein Einzeiler sein kann), um Ihre PNG-Generierung durchzuführen:

$ ls *.gv | entr ./update.sh /_ 

mit update.shentlang der Linien von:

neato -Tpng "$1" -o"$" 

Ich habe den obigen Ansatz mit einem einfachen Skript getestet, um mit imagemagick convertein Bild zu verwenden, das ohne Anführungszeichen funktionierte. Es ist jedoch besser, sie im Fall von Leerzeichen usw. in Dateinamen zu belassen.

Als Randbemerkung benutze ich entrohnehin ein Update-Skript, da es mir klarer geht. Zum Beispiel verwende ich entrLaTeX - Quelldateien zu sehen und eine aktualisierte PDF zu erzeugen, der Update - Skript in diesem Fall läuft xelatex, biberund erfrischt auch den PDF - Viewer ( pkill -HUP mupdf).

Vielen Dank! Unter diesen Umständen möchte ich jedoch lieber kein Skript erstellen. Wenn ich eine Unterstützungsdatei für das Erstellen erstellen würde, würde ich ein Makefile schreiben und den vorgeschlagenen Workflow verwenden: $ ls * .gv | entr machen ". Das Makefile funktioniert auch ohne Eingaben oder ähnliches, und Texteditoren unterstützen häufig das Aufrufen eines Makefiles (z. B. vim). Ich verwende vim und könnte einen automatischen Befehl zum Speichern von `: au BufWritePost aktivierenmachen ". Wenn ich möchte, dass make im Hintergrund läuft, kann ich vim-dispatch, asyncrun.vim, neomake, vim-accio oder eines der vielen anderen Plugins verwenden. Hotschke vor 6 Jahren 0
Übrigens, wissen Sie [latexmk] (https://ctan.org/pkg/latexmk)? Es ist Teil von TexLive. Es bietet die Option `$ latexmk -pvc`, die` entr 'überflüssig macht und die Programme Xelatex, Biber und andere genauso oft wie nötig aufruft und den Betrachter auffrischt. Hotschke vor 6 Jahren 0
@Hotschke fairer Punkt über Makefiles (und gute Antwort); Ich komme nicht aus einem Programmierhintergrund, also wäre es mehr Arbeit für mich, ihre Syntax zu lernen - auf der TODO-Liste - und dann je nach Kontext einen 1-zu-3-ish-Liner zu schreiben; Obwohl ich zugeben muss, fühlt es sich ein bisschen un-unixy an, nicht das richtige Werkzeug für den Job zu verwenden. bertieb vor 6 Jahren 0
IMHO Makefile-Syntax ist nicht wirklich intuitiv. Ich habe eine Weile gebraucht, um es zu lernen, und ich muss immer noch die Bedeutung von `$ <`, `$ +` und ähnlichem nachschlagen. Ich benutze es nicht oft genug und bevorzuge Latexmk für Latex und cmake für c / c ++. Hotschke vor 6 Jahren 0
1
Hotschke

Verwenden fswatchstattentr

Vielen Dank an @Attie für den Hinweis fswatch. Folgende Arbeiten für mich:

 $ fswatch -e ".*" -i "$PWD/[^.]*\\.gv$" -0 $PWD | xargs -0 -n 1 -I {} sh -c 'F={}; neato -Tpng "$F" -o"$"' 

fswatch berücksichtigt standardmäßig alle Dateien: Sie müssen Filter verwenden, um sich auf einen bestimmten Dateityp zu beschränken (siehe https://stackoverflow.com/q/34713278/ ).

https://emcrisostomo.github.io/fswatch/ von Enrico M. Crisostomo (2013-2017)

1
Hotschke

Ein Makefile verwenden

SOURCES:=$(shell find . -maxdepth 1 -name '*.gv')  ifndef OTYPE OTYPE:=png endif # use `make OTYPE=pdf` to generate pdfs  TARGETS:=$(SOURCES:.gv=.$(OTYPE))  .PHONY: all clean  all: $(TARGETS)  clean: rm $(TARGETS)  %.$(OTYPE) : %.gv neato -T$(OTYPE) $< -o$(basename $<).$(OTYPE) 

Jetzt können Sie verwenden

$ ls *.gv | entr make 

Es gibt Raum für Verbesserungen: Es gibt zwei Befehle, um Dateien mit der Erweiterung .gv aufzulisten, die einer einzigen Quelle der Wahrheit (SSOT) widersprechen .

Vim Hinweise

Sie können das Makefile auch im Texteditor vim verwenden

:mak[e] 

Sie können make beim Speichern automatisch aufrufen, indem Sie einen automatischen Befehl mit einrichten

:au BufWritePost <buffer> make 

Sie können ein Plugin für das Ausführen von async verwenden: Siehe Plugins vim-dispatch (Normalmodus-Mapping m<CR>), neomake oder asyncrun.vim .

Es gibt jedoch bereits Compiler-Definitionen für die Befehle dot und neato:

Das bedeutet, dass Sie kein Makefile schreiben müssen. Sie können den makeprg mit :comp[iler] neatooder einstellen :comp dot. Beachten Sie, dass Sie alle Compiler-Definitionen durch :comp <C-d>und Sie können die Tab-Vervollständigung :comp n<Tab>von :comp neatound :comp d<tab>bis anzeigen :comp dot.

Jetzt müssen Sie make mit einem Argument aufrufen, um Ihr Ausgabeformat anzugeben:

:make png :au BufWritePost <buffer> make png 

Wenn Sie vim-dispatch verwenden, sieht das so aus

:Make png m<Space>png<CR> :au BufWritePost <buffer> Make png 
0
Hotschke

Entr- /_Als Argument an eine Shell übergeben

ls *.gv | entr bash -c 'neato -Tpng "$0" -o"$"' /_ 

Diese Antwort stammt von https://bitbucket.org/eradman/entr/issues/75/run-command-on-single-file-wenn-changed#comment-44183153 .

Dieser Befehl führt den Befehl unbemerkt aus neato. Wenn Sie eine Rückmeldung in der Befehlszeile erhalten möchten, wenn entreine Dateiänderung erkannt wird, fügen Sie -xbash hinzu, um den ausgeführten Befehl anzuzeigen:

ls *.gv | entr bash -x -c 'neato -Tpng "$0" -o"$"' /_