Jest to zdecydowanie możliwe, jeśli polecenie może obsłużyć wejście przewodowe.
spawn zwraca obiekt ChildProcess, można przekazać do niego ciąg (lub binarny), zapisując go na jego stdin. Łańcuch powinien być najpierw converted na ReadableStream, następnie można napisać ciąg do stdin
z CLI przez pipe.
createReadStream tworzy ReadableStream z pliku.
Poniższy przykład pobiera plik pdf i przesyła zawartość do pdftotext
, a następnie wyświetla pierwsze kilka bajtów wyniku.
const source = 'http://static.googleusercontent.com/media/research.google.com/en//archive/gfs-sosp2003.pdf'
const http = require('http')
const spawn = require('child_process').spawn
download(source).then(pdftotext)
.then(result => console.log(result.slice(0, 77)))
function download(url) {
return new Promise(resolve => http.get(url, resolve))
}
function pdftotext(binaryStream) {
//read input from stdin and write to stdout
const command = spawn('pdftotext', ['-', '-'])
binaryStream.pipe(command.stdin)
return new Promise(resolve => {
const result = []
command.stdout.on('data', chunk => result.push(chunk.toString()))
command.stdout.on('end',() => resolve(result.join('')))
})
}
Dla CLIS nie mają możliwość odczytu z stdin
, można użyć named pipes.
Edytuj: Dodaj kolejny przykład z nazwanymi potokami.
Po utworzeniu nazwanych potoków można używać ich jako plików. Poniższy przykład tworzy tymczasowe nazwane potoki do wysyłania danych wejściowych i uzyskiwania danych wyjściowych oraz wyświetla pierwsze kilka bajtów wyniku.
const fs = require('fs')
const spawn = require('child_process').spawn
pipeCommand({
name: 'wvText',
input: fs.createReadStream('document.doc'),
}).then(result => console.log(result.slice(0, 77)))
function createPipe(name) {
return new Promise(resolve =>
spawn('mkfifo', [name]).on('exit',() => resolve()))
}
function pipeCommand({name, input}) {
const inpipe = 'input.pipe'
const outpipe = 'output.pipe'
return Promise.all([inpipe, outpipe].map(createPipe)).then(() => {
const result = []
fs.createReadStream(outpipe)
.on('data', chunk => result.push(chunk.toString()))
.on('error', console.log)
const command = spawn(name, [inpipe, outpipe]).on('error', console.log)
input.pipe(fs.createWriteStream(inpipe).on('error', console.log))
return new Promise(resolve =>
command.on('exit',() => {
[inpipe, outpipe].forEach(name => fs.unlink(name))
resolve(result.join(''))
}))
})
}
Hei @DarkKnight, dużo tranków !! Jeśli nie pytam o wiele, czy mógłbyś podać przykładowy efekt z nazwanymi potokami? Okazuje się, że używam innych skryptów, które nie obsługują innej metody. –
z pytaniem *, przykład * –
Wszystkie wymienione narzędzia mogą akceptować 'stdin' przez podanie' -'. Dodałem jeszcze inny przykład. – DarkKnight