Stdout

如何轉換為大寫的標準錯誤輸出而不是標準輸出?

  • January 7, 2018

我正在使用 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 fromcmd將像stdout一樣通過管道,而原始stdout已被重定向到stderr。該tr命令將進行大寫轉換。

**更新:**儘管您接受了願望清單上方的答案,但包括同時操作stdoutstderr的能力。因此,讓我們嘗試解決這個問題……請記住,我們遇到了一些我不經常做的事情!

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

我的健全性檢查工作正常,所以試一試。

引用自:https://unix.stackexchange.com/questions/415184