Problemem jest to, że długość linii poleceń jest ograniczona, a *.json
produkuje zbyt wiele argumentów za jednym wierszu poleceń. Jednym rozwiązaniem jest rozbudować wzór w for
pętli, które nie mają znaczenia takie same ograniczenia jak w linii polecenia ponieważ bash
może iteracyjnego wyniku wewnętrznie zamiast konstruowania listę argumentów na polecenie zewnętrznej:
for f in *.json; do
cat "$f"
done | jq -s '.' > output.json
Jest to raczej nieefektywne, ponieważ wymaga jednorazowego uruchomienia cat
dla każdego pliku. Bardziej wydajnym rozwiązaniem jest użycie find
do wywoływania cat
z jak największą liczbą plików za każdym razem.
find . -name '*.json' -exec cat '{}' + | jq -s '.' > output.json
(może być w stanie po prostu użyć
find . -name '*.json' -exec jq -s '{}' + > output.json
jak dobrze, może to zależeć od tego, co jest w plikach i jak wiele połączeń do jq
używając opcji -s
porównuje się do jednego połączenia.)
To nie jest dla mnie oczywiste, że mogę to zrobić, ponieważ AFAIK to, co robiłem, to wzięcie kilku pojedynczych obiektów Json '{...}' i umieszczenie ich w dobrze uformowanej tablicy obiektów [{...}, {...}, {...}] '. czy to się nadal dzieje z tym, co proponujesz? – Kristian
[Nie używaj 'ls' w ten sposób] (http://mywiki.wooledge.org/ParsingLs). Możesz po prostu użyć pętli 'for' zamiast:' for f in * .json; zrobić kota "$ f"; zrobione | jq -s '.''. (Faktycznie, 'ls * .json' nie powiedzie się z tego samego powodu co oryginał: zbyt wiele argumentów linii poleceń wynikających z rozszerzenia nazwy ścieżki.) – chepner
Nie polecałbym używania' find' w ten sposób, chociaż Naprawdę tylko stwarza problem, jeśli jeden z plików JSON miał znak nowej linii w swojej nazwie.Niektóre inne nazwy plików mogą być problematyczne, ale mogą być obsługiwane za pomocą 'IFS = read -r f' zamiast tego. – chepner