Stdout
如何轉換為大寫的標準錯誤輸出而不是標準輸出?
我正在使用 rsync 備份一些文件:
rsync -PaSh --stats --delete -e "-i key -p XXXX" "/source/" username@192.168.0.1:/destination/ 2> output.txt | grep -e 'bytes received' -e 'total bytes' -e files -e 'total file size:' >> output.txt
因為有數千個文件,我只想看到任何錯誤和最後的摘要。
上面的命令輸出這個:
rsync: delete_file: unlink(test/test.txt) failed: Permission denied (13) Number of files: 12 (reg: 10, dir: 2) Number of created files: 0 Number of regular files transferred: 0 sent 382 bytes received 137 bytes 41.52 bytes/sec
我只想將任何錯誤轉換為大寫(以引起對它們的注意)並保持摘要不變。
所以它看起來像這樣:
RSYNC: DELETE_FILE: UNLINK(TEST/TEST.TXT) FAILED: PERMISSION DENIED (13) Number of files: 12 (reg: 10, dir: 2) Number of created files: 0 Number of regular files transferred: 0 sent 382 bytes received 137 bytes 41.52 bytes/sec
我怎樣才能做到這一點?
謝謝
您可以藉助臨時文件描述符(此處為 fd 3)有效地交換標準輸入和標準輸出:
cmd 3>&2 2>&1 1>&3- | tr '[:lower:]' '[:upper]'
這就是說“將新 fd 指向 stderr 指向的位置,將stderr**指向stdout指向的位置,將stdout指向stderr最初指向的位置”……很容易,對吧?:)
或者換句話說:現在stderr from
cmd
將像stdout一樣通過管道,而原始stdout已被重定向到stderr。該tr
命令將進行大寫轉換。**更新:**儘管您接受了願望清單上方的答案,但包括同時操作stdout和stderr的能力。因此,讓我們嘗試解決這個問題……請記住,我們遇到了一些我不經常做的事情!
stdout / stderr的簡單交換不會做任何有用的事情。無論有沒有交換,您都不能通過單個管道使用兩個不同的流。作為替代方案,首先想到的是使用 FIFO(命名管道):
mkfifo /tmp/fifo1 /tmp/fifo2 # run the key command in the background, in a subshell to suppress # job control messages (e.g. "[1] 12345" and "[1]+ Exit ...") ( cmd > /tmp/fifo1 2> /tmp/fifo2 & ) # concatenate tr/stderr and grep/stdout using process substitution # (I'm assuming the summary information occurs at the end of rsync output) cat <(cat /tmp/fifo2 | tr '[:lower:]' '[:upper:]') <(grep ... /tmp/fifo1) rm -f /tmp/fifo1 /tmp/fifo2
如果願意,您實際上可以將所有這些放在一條線上!
mkfifo /tmp/fifo1 /tmp/fifo2; (cmd > /tmp/fifo1 2> /tmp/fifo2 &); cat <(cat /tmp/fifo2 | tr '[:lower:]' '[:upper:]') <(grep ... /tmp/fifo1); rm -f /tmp/fifo1 /tmp/fifo2
我的健全性檢查工作正常,所以試一試。