2012-04-19 2 views
18

Можно ли использовать скрипт bash для форматирования вывода ls в массив json? Чтобы быть действительным json, все имена файлов и файлов должны быть заключены в двойные кавычки, разделенные запятой, и все это нужно обернуть в квадратные скобки. То есть конвертировать:преобразовать bash `ls` output в json array

[email protected]:~/Desktop$ ls 
foo.txt bar baz 

в

[ "foo.txt", "bar", "baz" ] 

редактировать: я сильно предпочитаю то, что работает на всех моих серверов Linux; следовательно, скорее не зависят от python, а имеют чистое решение bash.

+0

Вы используете неправильный инструмент для работы. Если вы беспокоитесь о недоступности python, используйте perl. Он должен быть на всех серверах Linux. – gpojd

+0

Кто-нибудь знает, как это сделать с помощью json-манипулятора jq? http://stedolan.github.io/jq/manual/ – rektide

ответ

12

Использование Perl в качестве кодера; это гарантированно быть не глючит, есть везде, и с трубами, это все еще достаточно чистый:

ls | perl -e 'use JSON; @in=grep(s/\n$//, <>); print encode_json(\@in)."\n";' 
+0

Не удалось, но ответ awk/sed работал. – FakeRainBrigand

+1

Вам необходимо установить модуль JSON perl, но это работает! – slm

+4

** - 1 **. Это страдает от классической проблемы [Parsing LS] (http://mywiki.wooledge.org/ParsingLs). Лучше сделать это в цикле for и полностью избежать трубы. См. Ответ Гленна Джекмана для правильного подхода. – ghoti

0

Personnaly, я бы запрограммировал скрипт, который выполнил бы команду ls, посылая вывод в файл по вашему выбору при разборе вывода, чтобы сделать формат его действительным JSON-форматом.

Я уверен, что простой файл Bash выполнит эту работу.

Bash ouput

13

Да, но случаи угловых и обработка Unicode отвезут вас на стену. Лучше делегировать язык скриптов, который поддерживает его.

$ ls 
あ a "a" à a b 私 
$ python -c 'import os, json; print json.dumps(os.listdir("."))' 
["\u00e0", "\"a\"", "\u79c1", "a b", "\u3042", "a"] 
+0

Спасибо, но действительно предпочитаю то, что обычно работает на любом Linux-сервере; поэтому я предпочитаю чистое решение Bash. – Jeroen

+6

У 99,8% серверов Linux есть Python; по общему признанию, вам может понадобиться использовать simplejson, хотя для более старых версий Python. –

+1

Сервер без python = Ад. Вероятно, вы тоже скоро получите решение perl. – KurzedMetal

0

Не можете ли вы использовать скрипт python следующим образом?

myOutput = subprocess.check_output["ls"] 
output = ["+str(e)+" for e in myOutput] 
return output 

Я не проверял, работает ли это, но вы можете найти спецификацию here

-1

Должно быть довольно легко.

$ cat ls2json.bash 
#!/bin/bash 
echo -n '[' 
for FILE in $(ls | sed -e 's/"/\\"/g') 
do 
echo -n \"${FILE}\", 
done 
echo -en \\b']' 

затем запустить:

$ ./ls2json.bash > json.out 

но питон будет еще проще

import os 
directory = '/some/dir' 
ls = os.listdir(directory) 
dirstring = str(ls) 
print dirstring.replace("'",'"') 
+0

Не могли бы вы добавить запятую, разделяющую две строки? – Jeroen

+0

о, да, забыл в переводе, исправлен, проблема в том, что будет конечная запятая. хмм. – TaoJoannes

+1

Ну что ж, дело в том, что после последнего элемента не должно быть запятой, прямо перед] – Jeroen

1

Вот Баш линию

echo '[' ; ls --format=commas|sed -e 's/^/\"/'|sed -e 's/,$/\",/'|sed -e 's/\([^,]\)$/\1\"\]/'|sed -e 's/, /\", \"/g' 

не будет правильно работать с ", \ или некоторые запятые в имени файла. Кроме того, если ls ставит новые строки между именами файлов, так и будет.

+0

Также не будет иметь дело с вкладками, символами новой строки или другими управляющими символами в именах файлов. – ghoti

10

Привет вы можете сделать это с SED и AWK:

ls | awk ' BEGIN { ORS = ""; print "["; } { print "\/\@"$0"\/\@"; } END { print "]"; }' | sed "s^\"^\\\\\"^g;s^\/\@\/\@^\", \"^g;s^\/\@^\"^g" 

EDIT: обновлен, чтобы решить проблему с " и пространств. Я использую /@ как шаблон замены для ", так как / недействительный символ для имени файла.

+0

Обратите внимание, что это решение неправильно выполняет двойные кавычки, которые могут быть в имени, например. файл с именем 'foo \" bar' выдается как '' foo "bar" 'вместо' 'foo \" bar "'. – Phrogz

+0

также являются каталогами с пробелом в названии. – Jeroen

+0

Я решил эти две проблемы – Tronix117

-1

Не используйте bash, используйте язык сценариев.Непроверенные Perl пример:

use JSON; 
my @ls_output = `ls`; ## probably better to use a perl module to do this, like DirHandle 
print encode_json(@ls_output); 
7
json="[" 
sep="" 
for file in *; do 
    file=${file//\\/\\\\} 
    file=${file//\"/\\\"} 
    printf -v json '%s%s"%s"' "$json" "$sep" "$file" 
    sep=, 
done 
json+="]" 
+1

Мне нравится, как вы обрабатывали запятую между элементами! – raychi

0

Я также искал способ вывести папку Linux/дерево файлов в какой-то JSON или XML-файл. Почему бы не использовать эту простую концевую команду:

$ дерева --dirsfirst --noreport -n -i -s -X -D -f -o my.xml

так, просто команда линукс дерева, и настройте свои собственные параметры. Здесь -X дает выход XML! Для меня это нормально, и я думаю, что есть какой-то скрипт для преобразования XML в JSON .. ПРИМЕЧАНИЕ: я думаю, https://unix.stackexchange.com/questions/90115/convert-output-of-tree-command-to-json-format/ охватывает тот же вопрос.

1

Большая часть машины Linux уже имеет питон. все, что вам нужно сделать, это:

python -c 'import os, json; print json.dumps(os.listdir("/yourdirectory"))' 

Это для. directory, вы можете добавить любой путь.

+1

. Ваш ответ кажется точный дубликат http://stackoverflow.com/a/10234470/817632 – Olga

+0

Как мне изменить это, чтобы также следовать каталогам? – user3662307

+0

вы можете сделать это для разных каталогов, используя python -c 'import os, json; print json.dumps (os.listdir ("/ mydirectory/temp")) ' –

9

Если вы знаете, что имя файла не содержит символ новой строки, используйте JQ:

ls | jq -R -s -c 'split("\n")'

Краткое объяснение флагов JQ:

  • -R обрабатывает входные данные как строки вместо JSON
  • -s объединяет все линии в массив
  • -c создает компактный выход

Для этого требуется версия 1.4 или новее jq. Попробуйте это, если он не работает для вас:

ls | jq -R '[.]' | jq -s -c 'add'

+0

error: split не определено split ("\ n") ^^^^^ 1 компилировать ошибку –

+0

Я попробовал оба 'ls | jq -R -s -c 'split ("\ n")' и 'ls | jq -R '[.]' | jq -s -c 'add''. Первая имеет добавочную пустую строку "", добавленную в массив. Таким образом, последнее является лучшим решением. – Devy