天天看點

Bash能夠處理二進制資料嗎?

作者:SuperOps
Bash能夠處理二進制資料嗎?

Bash能夠處理二進制資料嗎?

基本上,答案是否定的。

盡管bash的二進制資料處理能力比舊的shell要強,但它仍然無法處理任意二進制資料。具體而言,shell變量不是100%的二進制清潔的,是以不能在它們中存儲二進制檔案。

您可以将uuencode的ASCII資料存儲在變量中,例如:

var=$(uuencode /bin/ls ls)
cd /somewhere/else
uudecode <<<"$var"  # 不要忘記加引号!           

請注意:GNU和Unix的uuencode/uudecode之間有很大的差別。在Unix的uudecode中,您無法指定輸出檔案;它總是使用在ASCII資料中編碼的檔案名。我已經修複了以前的示例,使其在Unix系統上可以工作。如果您進行進一步更改,請不要使用GNUisms。

有時候,在使用netpbm時存儲小的臨時位圖檔案會很友善。在這種情況下,我通過在管道中添加pnmnoraw指令來建立(較大的)ASCII檔案,這樣bash在存儲時不會出現問題。

如果您有冒險精神,請考慮進行以下實驗:

# bindec.bash,嘗試将二進制資料解碼為ASCII十進制資料
IFS=
while read -n1 x ;do
    case "$x" in
        '') echo empty ;;
        # 在此處插入以下單行代碼生成的256行代碼:
        # for x in $(seq 0 255) ;do echo "        #39;\\$(printf %o $x)') echo $x;;" ;done
    esac
done           

然後将二進制資料輸入到它中,例如:

for x in $(seq 0 255) ;do echo -ne "\\$(printf %o $x)" ;done | bash bindec.bash | nl | less           

這表明0字元被完全跳過了,因為我們無法使用輸入生成它,是以大多數我們嘗試處理的二進制檔案會友善地遭到破壞。

是的,Bash是用C編寫的,并使用C語義來處理字元串(包括NUL位元組作為字元串終止符)在其變量中。您無法在Bash變量中安全地存儲NUL。它從來沒有打算用于這個目的。--GreyCat

請注意,這指的是将二進制資料存儲在變量中。使用管道在程式之間移動資料始終是二進制清潔的。臨時檔案也是安全的,隻要在建立它們時采取适當的預防措施。

如果沒有外部指令可用,隻使用bash内置指令來cat二進制檔案(當/lib/libgcc_s.so.1被重命名時,我曾經使用過這個技巧,挽救了當時的局面):

# 僅使用bash内置指令模拟cat,二進制安全
IFS=
while read -d '' -r -n1 x ; do
    case "$x" in
        '') printf "\x00";;
        *) printf "%s" "$x";;
    esac
done           

如果沒有-n1,您必須小心處理最後一個\0後的資料,例如循環後[[ $x ]] && printf "%s" "%x"。我沒有測試過它是否可行或是否足夠。此外,如果您讀取一個沒有任何\0的大檔案,我不知道會發生什麼。--pgas

知識點: uunencode指令行工具

在 Bash 中,uuencode 是一個用于将二進制檔案轉換成可列印的 ASCII 碼表示形式的指令。該指令的文法如下:

uuencode [輸入檔案] [輸出檔案]           

其中,輸入檔案是要編碼的二進制檔案,輸出檔案是編碼後的 ASCII 碼檔案。uuencode 指令将輸入檔案轉換成一種稱為 uuencode 格式的 ASCII 碼表示形式,并将結果輸出到輸出檔案中。

uuencode 指令通常用于将二進制檔案轉換成文本格式,以便通過電子郵件或其他文本傳輸方式發送。由于某些電子郵件系統隻能傳輸文本資料,是以 uuencode 可以将二進制檔案編碼成文本格式,然後再通過電子郵件發送。

要解碼 uuencode 編碼的檔案,可以使用 Bash 中的 uudecode 指令。uudecode 指令将 uuencode 格式的 ASCII 碼檔案解碼為原始的二進制檔案。

uuencode 指令可以将二進制檔案編碼為 ASCII 碼格式,以便通過電子郵件等文本傳輸方式發送,而 uudecode 指令可以将 uuencode 格式的 ASCII 碼檔案解碼為原始的二進制檔案。

如果在 Bash 中運作 uuencode 指令時出現 "uuencode: 未找到指令" 的錯誤消息,可能是因為 uuencode 指令沒有安裝或沒有添加到系統的 PATH 環境變量中。

在大多數 Linux 發行版中,uuencode 指令通常包含在 sharutils 或 uuencode 包中。您可以使用以下指令來安裝它們:

在基于 Debian 或 Ubuntu 的系統中:

sudo apt-get install sharutils           

在基于 Red Hat 或 CentOS 的系統中:

sudo yum install sharutils           

在安裝完成後,您可以嘗試再次運作 uuencode 指令,如果仍然出現相同的錯誤消息,則需要檢查 PATH 環境變量是否包含 uuencode 指令所在的目錄。可以使用以下指令來檢視 PATH 環境變量的值:

echo $PATH           

如果 uuencode 指令所在的目錄沒有包含在 PATH 環境變量中,可以使用以下指令将其添加到 PATH 環境變量中(假設 uuencode 指令所在的目錄為 /usr/bin):

export PATH=$PATH:/usr/bin           

添加完畢後,您可以再次嘗試運作 uuencode 指令,應該就可以正常工作了。

了解更多shell實用技巧,快速掌握大廠一線經驗

如果您覺得文章内容對你有一點幫助可以關注我,我在頭條平台會持續分享更多實用的shell技巧和最佳實踐,如果想系統的快速學習shell的各種高階用法和生産環境避坑指南可以看看《shell腳本程式設計最佳實踐》專欄,專欄裡有更多的實用小技巧和腳本代碼分享。

繼續閱讀