Bash, dahili olarak boş baytlarla sonlandırılan C tarzı dizeleri kullanır. Bu, bir Bash dizesinin (örneğin bir değişkenin değeri veya bir komutun argümanı gibi) aslında boş bir bayt içeremeyeceği anlamına gelir. Örneğin, bu mini script:
foobar=$'foo\0bar' # foobar='foo' + null byte + 'bar'
echo "${#foobar}" # print length of $foobar
aslında yazdırır 3, çünkü $foobaraslında sadece 'foo': bardizgenin sonundan sonra gelir.
Benzer şekilde, echo $'foo\0bar'sadece baskı yapar foo, çünkü kısmı echobilmez \0bar.
Gördüğünüz gibi, \0sıra bir $'...'stil dizesinde aslında çok yanıltıcıdır ; dize içinde boş bir bayt gibi görünüyor, ancak bu şekilde çalışma sonunda bitmiyor. İlk örneğinizde reademrinizde var -d $'\0'. Bu işe yarıyor, fakat -d ''aynı zamanda işe yarıyor! (Yani bir açıkça belgelenmiş bir özellik değil read, ama aynı nedenle çalışır varsayalım: ''Boş dize, sonlandırıcı boş bayt hemen gelir böylece. "Nin ilk karakteri kullanılarak belgelenmiştir delim ", ben bile eserlerini tahmin "ilk karakter" dizenin sonundan sonraysa!)-d delim
Eğer bildiğimiz gibi Ama findörneğin, o ise bir komut boş byte çıktısını ve bu bayt girdi olarak okur başka bir birliğe yöneltilen için mümkün müdür. Bunun hiçbir kısmı, Bash içindeki bir dizgede boş bir bayt depolamaya dayanmaz . İkinci örneğinizle ilgili tek sorun, $'\0'bir komutun argümanında kullanamamız ; echo "$file"$'\0'Sonunda boş byte'ı mutlu bir şekilde yazdırabilirdi.
Dolayısıyla kullanmak yerine, stil dizeleriyle aynı türde kaçış dizilerini destekleyen echokullanabilirsiniz . Bu şekilde, bir dize içinde boş bir bayta sahip olmak zorunda kalmadan boş bir bayt yazdırabilirsiniz. Bu şuna benzerdi:printf$'...'
for file in * ; do printf '%s\0' "$file" ; done \
| while IFS= read -r -d '' ; do echo "$REPLY" ; done
ya da sadece bu:
printf '%s\0' * \
| while IFS= read -r -d '' ; do echo "$REPLY" ; done
(Not: echoaslında boş bir baytı -eişlemesine \0ve yazdırmasına izin verecek bir bayrak da vardır ; ancak dosya adınızdaki herhangi bir özel diziyi işlemeye de çalışacaktır. Bu nedenle printfyaklaşım daha sağlamdır.)
Bu arada, bazı kabukları vardır do boş iç dizeleri bayt izin verir. Örneğin, Zsh'de örneğin çalışır (varsayılan ayar varsayarak). Bununla birlikte, kabuğunuzdan bağımsız olarak, Unix benzeri işletim sistemleri programlara argümanların içine boş baytlar eklemek için bir yol sağlamaz (çünkü program argümanları C tarzı dizgiler olarak iletilir), bu nedenle her zaman bazı sınırlamalar olacaktır. Çünkü sadece (Sizin örnek Zsh çalışabilir echobir kabuk yerleşiğidir Zsh diğer programları çağırmak için OS desteğine güvenerek olmadan çağırmak, böylece. Eğer kullandıysanız command echoyerine echo, bu yerleşiğini atlanır ve bağımsız kullanıldığı böylece echoprogramı $PATH, Zsh'de aynı davranışı Bash ile aynı şekilde görürsünüz.)
-d ''Sınırlandırmak için zaten bir araç varsa, IFS neden hiçbir şeye ayarlanmamış\0? Burada bir açıklama buldum: stackoverflow.com/questions/8677546/…