2015-04-15 2 views
1

Я пытаюсь сбросить груз SQLite таблиц в формате .csv из CMD строки с помощью xargs, т.е.перенаправлять вывод команды запуска под xargs отдельно каждый файл

find . -name "*.db" -print0 \ 
    | xargs -0 -I {} sqlite3 -header -csv {} "select * from pulse_data;" > {}.csv 

По какой-то причине его написания {}.csv, а не каждый .db файл в свою очередь.

Есть ли проблема с использованием нотации {} более одного раза?

Если я запускаю его без редиректа это, кажется, работает, как ожидалось, то есть

find . -name "*.db" -print0 \ 
    | xargs -0 -I {} sqlite3 -header -csv {} "select * from pulse_data;" 

просто печатает все .db таблицы на стандартный вывод, как ожидается, в формате .csv

Как я могу получить его перенаправить на файл с соответствующим именем, то есть <file-name>.db.csv?

+0

В качестве дополнения, которое может объяснить немного больше/лучше _why_ происходило первоначальное поведение, кстати - перенаправления выполняются оболочкой * до того, как запускается команда; поэтому к моменту запуска «xargs» перенаправление stdout в файл с именем '{}' уже произошло. (Я отредактировал свой ответ, чтобы сделать это явным). –

ответ

1

xargs не запускает оболочку, поэтому вы не можете выполнять перенаправления оболочки из нее (если только ваша команда явно не указана xargs sh -c ...). В коде, указанном в вопросе, >{} выполняется родительской оболочкой до того, как xargs даже запущен - он вообще не знает о попытке перенаправления.

Поскольку вы ничего не делаете здесь, что значительно выигрывает от xargs (например, параллелизма), стоимость запуска снарядов под ним не оправдана. Просто прочитайте список из своей внешней оболочки.

while IFS= read -r -d '' filename; do 
    sqlite3 -header -csv "$filename" "select * from pulse_data;" >"$filename.csv" 
done < <(find . -name '*.db' -print0) # See footnote 1 

Если вы действительно хотите использовать xargs по какой-то причине:

find . -name '*.db' -print0 \ 
    | xargs -0 sh -c ' 
     for filename; do 
     sqlite3 -header -csv "$filename" "select * from pulse_data;" >"$filename.csv" 
     done' _ {} + 

Сноска 1: Обратите внимание, что <() особенность нет в POSIX ш - но КШ, ЗШ и баш все это получит; если вам нужна совместимость с /bin/sh, вы можете использовать трубку от find до петли while, но имейте в виду, что this comes with some caveats.

+0

не особо - просто куча файлов .db мне нужно преобразовать в .csv, не желая делать это вручную с помощью графического интерфейса, поэтому нужна подходящая альтернативная линия cmd для выполнения работы - какой бы простой метод ни был, находясь в поиске – bph

Смежные вопросы