J'ai récemment réalisé que nous pouvons utiliser cat
autant que dd
, et c'est en fait plus rapide que dd
Je sais que dd
était utile pour traiter les bandes où la taille des blocs importait réellement en termes d'exactitude, pas seulement de performances. De nos jours, cependant, existe-t-il des situations où dd
peut faire quelque chose cat
ne peut pas? (Ici, je considérerais une différence de performance inférieure à 20% non pertinente.)
Des exemples concrets seraient Nice!
En apparence, dd
est un outil d'un système d'exploitation IBM qui a conservé son apparence étrangère (son passage de paramètres), qui exécute certaines fonctions très rarement utilisées (comme EBCDIC pour ASCII conversions ou inversion de l'endianité… ce n'est pas un besoin courant de nos jours).
I pensait autrefois que dd
était plus rapide pour copier de gros blocs de données sur le même disque (en raison d'une utilisation plus efficace de la mise en mémoire tampon), mais cela n'est pas vrai , au moins sur les systèmes Linux d'aujourd'hui.
Je pense que certaines des options de dd
sont utiles lorsqu'il s'agit de bandes, où la lecture est vraiment effectuée dans des blocs (les pilotes de bande ne masquent pas les blocs sur le support de stockage comme le font les pilotes de disque). Mais je ne connais pas les détails.
Une chose que dd
peut faire et qui ne peut (facilement) être effectuée par aucun autre outil POSIX est de prendre les N premiers octets d'un courant. De nombreux systèmes peuvent le faire avec head -c 42
, Mais head -c
, Bien que courant, n'est pas dans POSIX (et n'est pas disponible aujourd'hui sur, par exemple, OpenBSD). (tail -c
Est POSIX.) De plus, même là où head -c
Existe, il peut lire trop d'octets de la source (car il utilise la mémoire tampon stdio en interne), ce qui est un problème si vous lisez à partir d'un fichier spécial où la simple lecture a un effet. (Les coreutils actuels de GNU lisent le nombre exact avec head -c
, Mais FreeBSD et NetBSD utilisent stdio.)
Plus généralement, dd
donne une interface à l'API de fichier sous-jacente unique parmi les outils Unix: seul dd
peut écraser ou tronquer un fichier à tout moment ou cherche dans un fichier. (Il s'agit de la capacité unique de dd
, et elle est grande; curieusement, dd
est surtout connue pour les choses que d'autres outils peuvent faire.)
>
Dans le shell.>>
Dans le shell, ou avec tee -a
.Si vous souhaitez raccourcir un fichier en supprimant toutes les données après un certain point, cela est pris en charge par le noyau sous-jacent et l'API C via truncate
, mais non exposée par aucun outil de ligne de commande sauf dd
:
dd if=/dev/null of=/file/to/truncate seek=1 bs=123456 # truncate file to 123456 bytes
Si vous voulez écraser les données au milieu d'un fichier, encore une fois, cela est possible dans l'API de sous-traitance en ouvrant le fichier pour l'écrire sans tronquer (et en appelant lseek
pour se déplacer à la position souhaitée si nécessaire), mais seulement dd
peut ouvrir un fichier sans tronquer ou ajouter, ou chercher à partir du Shell ( exemple plus complexe) ).
# zero out the second kB block in the file (i.e. bytes 1024 to 2047)
dd if=/dev/zero of=/path/to/file bs=1024 seek=1 count=1 conv=notrunc
Donc… En tant qu'outil système, dd
est pratiquement inutile. En tant qu'outil de traitement de texte (ou fichier binaire), c'est très utile!
La commande dd
inclut BEAUCOUP d'options que cat n'est pas en mesure d'accueillir. Peut-être que dans vos cas d'utilisation, le chat est un substitut réalisable, mais ce n'est pas un remplacement dd.
Un exemple serait d'utiliser dd
pour copier une partie de quelque chose mais pas le tout. Vous souhaitez peut-être extraire certains des bits du milieu d'une image iso ou de la table de partition d'un disque dur en fonction d'un emplacement connu sur le périphérique. Avec dd
, vous pouvez spécifier les options de démarrage, d'arrêt et de quantité qui permettent ces actions.
Ces options de dd
le rendent indispensable pour une manipulation fine des données alors que cat
* ne peut fonctionner que sur des objets, des périphériques ou des flux de fichiers entiers.
* Comme l'a noté Gilles dans les commentaires, il est possible de combiner cat
avec d'autres outils pour isoler des parties de quelque chose, mais cat
fonctionne toujours sur l'objet entier.
Personne n'a encore mentionné que vous pouvez utiliser dd pour créer fichiers épars , bien que truncate
puisse également être utilisé dans le même but.
dd if=/dev/zero of=sparse-file bs=1 count=1 seek=10GB
C'est presque instantané et crée un gros fichier arbitraire qui peut être utilisé comme fichier de bouclage par exemple:
loop=`losetup --show -f sparse-file`
mkfs.ext4 $loop
mkdir myloop
mount $loop myloop
Ce qui est bien, c'est qu'au départ, il n'utilise qu'un seul bloc d'espace disque, puis ne croît que si nécessaire (le formatage ext4 d'un fichier de 10 Go consomme 291 Mo sur mon système). Utilisez du
pour voir combien d'espace disque est réellement utilisé - ls
indique uniquement la taille maximale du fichier.
Remplacer des segments spécifiques d'un disque dur avec quelque chose est un exemple courant. Par exemple, vous souhaiterez peut-être supprimer votre MBR à l'aide de cette commande:
dd if=/dev/zero of=/dev/sda bs=446 count=1
Vous pouvez également créer des fichiers vides avec lui (par exemple pour les images de disque en boucle):
dd if=/dev/zero of=10mb.file bs=1024k count=10
dd
est très utile pour sauvegarder le secteur de démarrage d'un disque dur ou d'un autre périphérique de stockage (dd if=/dev/sda of=boot_sector.bin bs=512 count=1
) puis la réécrire ultérieurement (dd if=boot_sector.bin of=/dev/sda
). Il est également utile pour sauvegarder les en-têtes des volumes chiffrés.
cat
pourrait être tordu en faisant cela, mais je ne lui ferais pas confiance pour la partie réécriture. Il est difficile de faire en sorte que cat
ne lise/écrive qu'un certain nombre d'octets.
J'ai récemment eu à cloner des partitions de plusieurs centaines de Go pour la première fois de mon histoire de linuxing (c.f cp -ar
ou rsync
qui m'ont bien servi plusieurs fois). Bien sûr, je me suis tourné vers dd
'car tout le monde sait que c'est ce que vous utilisez ... et j'ai été consterné par la performance. Un peu de recherche sur Google m'a rapidement conduit à ddrescue
, que j'ai utilisé plusieurs fois maintenant et qui fonctionne très bien (beaucoup plus rapidement que dd).
Voici quelques trucs dd que j'ai trouvé au fil des ans ..
Si vous êtes dans une situation où EOF/^ D/^ F n'est pas détecté, vous pouvez utiliser dd pour transférer des fichiers texte vers un hôte. Puisqu'il arrêtera automatiquement la lecture après un nombre spécifié d'octets.
J'ai utilisé cela aussi récemment que l'année dernière lors d'un exercice de sécurité où nous avons pu obtenir des shells non tty sur un hôte distant et nous devions transférer des fichiers.
En fait, j'ai même créé quelques fichiers binaires en les encodant en base64 et en utilisant un script de décodage base64 pur mais bash pur mais fiable.
dd of=textfile.txt bs=1 count=<size_of_data_in_paste_buffer>
Une astuce super cool est que pendant l'exécution de dd, si vous lui envoyez un signal USR1, il émettra son état actuel (octets lus, octets par seconde ..)
J'ai écrit ceci pour agir comme un filtre de progression bash pur pour tout programme qui émet des données via stdout. (Remarque: à peu près n'importe quoi émettra des données via stdout - pour les programmes qui ne le font pas, vous pouvez tricher s'ils ne vous découragent pas en utilisant/dev/stdout comme nom de fichier. Mais l'idée est fondamentalement, chaque fois que vous obtenez X quantité d'octets, imprimer les marques de hachage (comme le FTP old school lorsque le mode de hachage était activé)
(Remarque) Le fichier de progression est boiteux, c'était surtout une preuve de concept. Si je le refaisais, j'utiliserais juste une variable.
dd bs=$BLKSZ of=${TMPFILE} 2>&1 \
| grep --line-buffered -E '[[:digit:]]* bytes' \
| awk '{ print $1 }' >> ${PROGRESS} &
while [[ $(pidof dd) -gt 1 ]]; do
# PROTIP: You can sleep partial seconds
sleep .5
# Force dd to update us on it's progress (which gets
# redirected to $PROGRESS file.
pkill -USR1 dd
local BYTES_THIS_CYCLE=$(tail -1 $PROGRESS)
local XFER_BLKS=$(((BYTES_THIS_CYCLE-BYTES_LAST_CYCLE)/BLKSZ))
if [ $XFER_BLKS -gt 0 ]; then
printf "#%0.s" $(seq 0 $XFER_BLKS)
BYTES_LAST_CYCLE=$BYTES_THIS_CYCLE
fi
done
Voici un exemple extrêmement pseudo-code de la façon dont vous pouvez avoir un fichier tar signé que vous pouvez extraire sans erreurs en fournissant une entrée tar via un descripteur de fichier anonyme - sans utiliser de fichiers tmp pour stocker des données de fichier partielles.
generate_hash() {
echo "yay!"
}
# Create a tar file, generate a hash, append it to the end
tar -cf log.tar /var/log/* 2>/dev/null
TARFILE_SIZE=$(stat -f "%z" log.tar)
SIGNATURE=$(generate_hash log.tar)
echo $SIGNATURE >>log.tar
# Then, later, extract without getting an error..
tar xvf <(dd if=$OLDPWD/log.tar bs=1 count=${TARFILE_SIZE})
Le tl; dr est: je trouve que dd est incroyablement utile. Et ce ne sont que les trois exemples auxquels je peux penser du haut de ma tête.
Vous pouvez rediriger du contenu de sortie. C'est particulièrement utile, si vous avez besoin d'écrire avec Sudo
:
echo some_content | Sudo dd status=none of=output.txt
Outre Sudo
, il équivaut à:
echo some_content > output.txt
ou à ceci:
echo some_content | Sudo tee output.txt > /dev/null