awk et newlines dans datatables d'input

Je veux find des files dans un directory et les identifier par leur mimetype, pas par l'extension des files.

J'utilise cette command pour déterminer le type de mime:

% find . -type f -print0 | xargs -0 -I{} file --mime-type {} ./foo bar.png: image/png ./OWoHp.png: image/png ./J7ZwV.png: image/png ./foo.txt: inode/x-empty ./bar: inode/x-empty ./hUXnc.png: image/png 

Le premier file a une nouvelle ligne dans le nom de file:

 % ls foo$'\n'bar.png foo?bar.png 

C'est ok et le file ne devrait pas être renommé.

Avec la command suivante, je veux filterr tous les files qui ne sont pas des images.

 % find . -type f -print0 | xargs -0 -I{} file --mime-type {} | awk -F$"\0" -F": " '/image/ {print $1}' bar.png ./OWoHp.png ./J7ZwV.png ./hUXnc.png 

et identifier leurs tailles:

 % find . -type f -print0 | xargs -0 -I{} file --mime-type {} | awk -F$"\0" -F":" '/image/ {print $1}' | xargs -I{} identify -format "%[fx:w*h] %i\n" {} identify: unable to open image `bar.png': No such file or directory @ error/blob.c/OpenBlob/2709. identify: unable to open file `bar.png' @ error/png.c/ReadPNGImage/3922. 26696 ./OWoHp.png 47275 ./J7ZwV.png 37975 ./hUXnc.png 

Mais cela ne fonctionne pas car il n'y a pas de file avec le nom bar.png . Le nom correct est

 ./foo bar.png 

avec une nouvelle ligne dans le nom.

Vous pouvez utiliser la construction -exec sh -c '...' avec find :

 find . -type f -exec sh -c 'file --brief --mime-type "$0" | \ grep -q ^image/ && identify -format "%[fx:w*h] %i\n" "$0"' {} \; 

ou avec exiftool :

 exiftool -q -if '$mimetype =~ /image/' -p '$megapixels $directory/$filename' -r . 

Je pense que votre meilleur pari sera d'utiliser une boucle de shell au lieu de xargs: Vous pouvez alors contrôler comment les commands sont envoyées l'argument de nom de file.

 find . -type f -print0 | while IFS= read -rd "" filename; do type=$( file --brief "$filename" ) if [[ $type == *image* ]]; then identify -format "%[fx:w*h] %i\n" "$filename" fi done 

Comme le souligne steeldriver, votre problème n'est pas awk , c'est un file . Il n'y a pas de NUL dans l'input que vous donnez à awk car le file mangé. Je ferais tout cela dans la coquille à la place:

 find . -type f -print0 | while IFS= read -r -d '' file; do file --mime-type "$file" | grep -qP "\bimage/" && printf '%s %s\0' $(identify -format '%[fx:w*h]' "$file") "$file"; done | sort -gz | tr '\0' '\n' 256 ./file 10 256 ./file 15 484 ./file 16 576 ./file 11 576 ./file 17 1024 ./file 12 1024 ./file 19 2304 ./file 13 5625 ./file 14 15190 ./file 2 15680 ./file 1 16384 ./file 9 65536 ./file 18 145200 ./file 0 183531 ./file 6 364807 ./file 3 364807 ./file 4 364807 ./file 5 388245 ./file 8 550560 ./file 7 

J'ai inclus le sort puisque je suppose que vous essayez d'améliorer votre réponse ici . L'exemple ci-dessus a été exécuté sur des noms de file avec des espaces et un ( file\n3 avec une nouvelle ligne). Pour une raison quelconque, identify n'imprimera pas les lignes \0 -terminées, donc j'utilise printf place.