lewat dd lewati | cari offset sebagai heksadesimal

11
# dd if=2013-Aug-uptime.csv bs=1 count=1 skip=3 2> /dev/null
d
# dd if=2013-Aug-uptime.csv bs=1 count=1 skip=0x3 2> /dev/null
f

Mengapa perintah kedua menghasilkan nilai yang berbeda?

Apakah mungkin untuk melewatkan skip | seek offset ddsebagai nilai heksadesimal?

eadmaster
sumber

Jawaban:

18

Mengapa perintah kedua menghasilkan nilai yang berbeda?

Untuk alasan historis, ddanggap xsebagai operator multiplikasi. Jadi 0x3dievaluasi menjadi 0.

Apakah mungkin untuk melewatkan skip | seek offset ke dd sebagai nilai heksadesimal?

Tidak secara langsung, sejauh yang saya tahu. Seperti halnya penggandaan menggunakan operator x, Anda dapat mengakhiri angka apa pun dengan bberarti "kalikan dengan 512" (0x200) dan dengan Kberarti "kalikan dengan 1024" (0x400). Dengan GNU dd Anda juga dapat menggunakan akhiran M, G, T, P, E, Zdan Yberarti kalikan dengan 2 pangkat 20, 30, 40, 50, 60, 70, 80 atau 90, masing-masing, dan Anda dapat menggunakan bagian atas atau menurunkan kasus kecuali untuk bakhiran. (Ada banyak sufiks lain yang mungkin. Misalnya, EBberarti "kalikan dengan 10 18 " dan PiBberarti "kalikan dengan 2 50 ". Lihat info coreutils "block size"untuk informasi lebih lanjut, jika Anda memiliki instalasi GNU.)

Anda mungkin menemukan di atas misterius, anakronistis, dan culun ke titik absurditas. Jangan khawatir: Anda tidak sendirian. Untungnya, Anda bisa mengabaikan semuanya dan menggunakan substitusi aritmatika shell Anda sebagai gantinya (bash dan kerang yang sesuai dengan Posix lainnya akan berfungsi, serta beberapa kerang yang bukan-Posix). Shell memang memahami angka heksadesimal, dan itu memungkinkan berbagai operator aritmatika ditulis dengan cara normal. Anda hanya perlu mengelilingi ekspresi dengan $((...)):

# dd if=2013-Aug-uptime.csv bs=1 count=$((0x2B * 1024)) skip=$((0x37))
rici
sumber
Perhatikan bahwa $((...))ini adalah ekspansi aritmatika POSIX, ini bukan bash spesifik sama sekali, Anda tidak harus menggunakannya bashuntuk menggunakannya, shell POSIX apa pun akan melakukannya. Namun perhatikan bahwa dalam banyak shell termasuk bash, ia mengalami pemisahan kata sehingga harus dikutip.
Stéphane Chazelas
@StephaneChazelas: Itu benar, tidak spesifik untuk bash. Namun, tidak perlu mengutip. (Posix: "Ekspresi harus diperlakukan seolah-olah dalam tanda kutip ganda, kecuali bahwa tanda kutip ganda di dalam ekspresi tidak diperlakukan secara khusus.") Jika ada variabel dalam ekspresi, dan nilainya termasuk pemisah, maka itu bukan angka yang valid; menempatkan tanda kutip di sekitar $((...))tidak akan mengubah apa pun. Satu-satunya kasus saya dapat memikirkan di mana kutipan akan melakukan apa pun adalah jika Anda memiliki sesuatu seperti IFS=4tetapi itu akan menyebabkan semua jenis kekacauan lainnya.
rici
Bagian yang Anda kutip adalah tentang apa yang ada di dalamnya $((...)). POSIX jelas bahwa perluasan $((...))tunduk pada pemisahan kata . Meninggalkan salah satu dari ekspansi perintah / aritmatika / variabel yang tidak dikutip dalam konteks daftar adalah operator split + glob. Pengaturan IFS = 4 tidak akan menyebabkan semua masalah jika Anda tidak menggunakan operator split + glob di mana itu tidak diperlukan / diinginkan, dan mengatur IFS setiap kali Anda membutuhkan operator split + glob tersebut.
Stéphane Chazelas
@StephaneChazelas: ya, hasil numerik tergantung pemisahan kata. Tapi itu bilangan bulat. Jika Anda menetapkan IFSsesuatu yang mencakup angka, sesuatu yang saya tidak percaya pernah saya lakukan, maka Anda perlu mengutip. Agaknya, jika seseorang melakukan itu, ia akan sadar akan kebutuhan itu, karena itu hampir tidak mungkin dilakukan dengan santai. Atau, setidaknya, itu bukan sesuatu yang mungkin akan saya lakukan, titik. Saya tidak bermaksud berbicara untuk Anda.
rici
1
@ogurets: cangkang apa yang Anda gunakan? (Harap sertakan versi).
rici
0

Saya tahu ini adalah utas lama, tetapi masalah ini masih tetap seperti biasanya, terutama ketika orang idiot seperti saya pergi dan secara tidak sengaja mengingat dan mengeluarkan 'cp ​​fileA fileB' dari bash history ketika fileB belum check-in ke git tidak didukung , dan berisi beberapa jam pengkodean setelah semalaman: - /

Berkat konsep di utas ini, saya dapat sepenuhnya memulihkan file saya yang hilang, namun saya kehilangan milik saya di Virtual Private Server jarak jauh dengan disk 32Gb dan sangat sedikit RAM (menjalankan Ubuntu 18.04), dan semua perhatian saya menggunakan 'grep' sebagai di atas akan cepat mati dengan 'memori tidak mencukupi'

Dalam kasus saya itu hexdump -C /dev/sdX1 | grep 'shortString'yang menyelamatkan saya. Tidak seperti grep, ia hanya menampilkan representasi hex ASCII yang sangat narroy, jadi penting untuk hanya mencari string unik pendek, dan ingat bahwa bahkan itu dapat dibungkus. Setelah itu mengeluarkan beberapa alamat hex di mana ada kecocokan, saya dapat menggunakan 'dd' dengan cara yang sama seperti di atas, kecuali bahwa saya menemukan itu tampaknya default ke ukuran blok 4096, jadi saya tidak hanya harus konversikan byte heksadesimal menjadi desimal tetapi bagi dengan 4096 untuk skala ke 4k blok untuk parameter lewati dd - tidak membantu, jika nomor ini terlalu besar untuk dd pesan kesalahan sepertinya mengeluh tentang skip=tidak valid daripada nomor yang diteruskan ke itu .

Kudos kepada orang-orang yang menambahkan tips tentang menggunakan bash with $((0xabcd))to obasilion hex-> dec konversi :-)

Hanya kata akhir saya - Dalam kasus saya ada beberapa salinan dari file yang sama yang semuanya sangat dekat. Tetapi dengan mengurangi alamat terendah dari alamat tertinggi yang dilaporkan oleh hexdump, saya dapat mengidentifikasi sebuah ~ 5MB wilayah yang berisi semua salinan yang mungkin, yang berarti saya dapat menargetkan dd pada alamat terendah dan mengekstraksi seluruh wilayah itu ke file temp. Editor Vim sekarang menangani konten biner dengan cukup anggun sehingga Anda dapat memeriksa tempfile dan membentuknya kembali sesuai kebutuhan.

JonathanH-UK
sumber