Używanie funkcji find, xargs itp. Do generowania plików o podobnych nazwach

3

Mam folder pełen plików HTML:

001.htm
002.htm
003.htm
…

Chcę uruchomić na nich Pandoc, aby przekonwertować je na pliki Markdown o podobnych nazwach:

001.md
002.md
003.md

To polecenie działa na jednym z nich:

pandoc -f html -t markdown 001.htm -o 001.md

Chcę użyć findi xargsautomatycznie uruchomić podobne polecenie na każdym pliku w folderze.

Dotarłem tak daleko:

find *.htm | xargs -I {} -n 1 pandoc -f html -t markdown -o {}

... który obcina wszystkie pliki w katalogu, więc teraz pytam, zanim naprawdę złamać coś.

Co jest złego w moim poleceniu powyżej i / lub jaki jest zupełnie inny / bardziej wydajny sposób na zrobienie tego?

75 puzon
źródło

Odpowiedzi:

4

Udało mi się to zrobić dzięki tej 1 wkładce. Jeśli jesteś elastyczny o xargsi findczęści.

for f in ./*.htm; do pandoc -f html -t markdown "$f" -o "${f%.htm}.md"; done

Jeśli chcesz działać rekurencyjnie (czyli: wszystkie .htmpliki w bieżącym katalogu i wszystkie podkatalogi), to (zakładając bash 4+) możesz użyć globstaropcji powłoki:

shopt -s globstar
for f in ./**/*.htm; do pandoc -f html -t markdown "$f" -o "${f%.htm}.md"; done
Martín Canaval
źródło
2
+1. xargs nie pozwala na taką samą elastyczność modyfikacji plików. Czy nie zastąpi *.htmz $(find...)- nazwy plików ze spacjami zostaną prawidłowo obsługiwane w pierwszym przypadku, ale nie drugi.
glenn jackman
1
@glennjackman ile ustawić bash $IFSdo $'\n'do tej części kodu, w którym nie są problemem obowiązuje Case - newlines nadal są jednak.
Daniel Beck
Wow, są dwie lub trzy nowe rzeczy w wierszu poleceń, których mogę się nauczyć z tego fragmentu. Dzięki!
75. puzon
3

Używanie {}nie jest wystarczająco elastyczne w niektórych sytuacjach. To wydaje się być jednym z nich.

Możliwym obejściem może być -execskrypt z find:

find . -name '*.htm' -exec ./convert-to-md.sh {} \;

Plik skryptu powinien wyglądać podobnie do tego, w zależności od dokładnego pandocwiersza poleceń:

#!/bin/bash
pandoc -f html -t markdown -o "${1/.htm/.md}" "${1}"

Jeśli nie chcesz do tego tworzyć i zapisywać pliku skryptu, zawsze możesz wstawić bashkod skryptu:

find . -name '*.htm' | xargs -n 1 bash -c 'pandoc -f html -t markdown -o "${1/.htm/.md}" "${1}"' -

Dodatkowy -na końcu służy do wypełnienia $0bash, który zwykle zawiera nazwę skryptu powłoki, argumenty pozycyjne zaczynające się od $0.

To pozwala zachować przy użyciu find(nawet -print0i xargs -0jeśli jesteś obsługi dziwnych nazw plików), ale nie wymaga stworzenia osobnego pliku.

Daniel Beck
źródło
I tak nie findradzi sobie z dziwnymi nazwami plików? IIRC nigdy nie ma dobrego powodufind … -print0 | xargs -0 …
slhck
@slhck Newlines są prawidłowymi komponentami nazw plików. Poniżej pokazano, w jaki sposób powoduje to awarię skryptów:touch "$( echo -e 'foo\nbar' )" ; find . -name 'foo*bar' | xargs -n 1 echo File:
Daniel Beck
1

Wygląda na to, że brakuje {}ci polecenia pandoc

find . -name \*.htm | xargs -I {} -n 1 pandoc -f html -t markdown {} -o {}.md

Ale wtedy będziesz mieć nazwy plików 001.htm.md- będziesz musiał zdecydować, czy to jest problem.

Glenn Jackman
źródło