![如何按内容类型迭代所有文本视频声音和图像文件(无论扩展名)](https://linux22.com/image/198302/%E5%A6%82%E4%BD%95%E6%8C%89%E5%86%85%E5%AE%B9%E7%B1%BB%E5%9E%8B%E8%BF%AD%E4%BB%A3%E6%89%80%E6%9C%89%E6%96%87%E6%9C%AC%E8%A7%86%E9%A2%91%E5%A3%B0%E9%9F%B3%E5%92%8C%E5%9B%BE%E5%83%8F%E6%96%87%E4%BB%B6%EF%BC%88%E6%97%A0%E8%AE%BA%E6%89%A9%E5%B1%95%E5%90%8D%EF%BC%89.png)
我想对每个类别文本(包括代码脚本和 src 文件)、视频、声音和图像文件使用 4 个 for 循环。
显式检查扩展以执行类似的检查
for i in *.ext1 *.ext2 *.ext...
要求我指定每个类别可能的每个扩展,并且我正在寻找替代方法。
答案1
恐怕没有其他办法了。请记住,在 *nix 系统上,因此可能在您使用的任何操作系统上,扩展通常是可选的和装饰性的。这意味着您可以拥有根本没有扩展名的文件:
$ ls
foo1 foo10 foo2 foo3 foo4 foo5 foo6 foo7 foo8 foo9
$ for file in *; do file "$file"; done
foo1: PNG image data, 25 x 25, 8-bit/color RGBA, non-interlaced
foo10: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 8 bit, mono 22050 Hz
foo2: GIF image data, version 89a, 500 x 225
foo3: HTML document, Unicode text, UTF-8 text, with very long lines (1207)
foo4: MPEG sequence, v2, program multiplex
foo5: Ogg data, Vorbis audio, stereo, 44100 Hz, ~128000 bps
foo6: Audio file with ID3 version 2.2.0, contains: MPEG ADTS, layer III, v1, 160 kbps, 44.1 kHz, JntStereo
foo7: ISO Media, Apple QuickTime movie, Apple QuickTime (.MOV/QT)
foo8: RIFF (little-endian) data, AVI, 640 x 480, 30.00 fps, video: FFMpeg MPEG-4, audio: MPEG-1 Layer 3 (mono, 44100 Hz)
foo9: ASCII text
因此,唯一的选择是编写一个程序来提取文件类型,然后将其分类为您提到的类别之一。如果存在这样的工具,我不知道。
如果您确实想编写一个文件,可以从file
上面的方法开始,然后定义哪些文件类型应属于哪个类别并从那里获取。但不会有 shell 本机方法可以为您完成此操作。
答案2
基于@terdon的答案(简而言之:“使用文件”),你可以这样做:
file --mime-type * |
awk -F': ' '$2 ~ /^video/ { system("process_video_file.sh " $1) ; next };
$2 ~ /^image/ { system("process_image_file.sh " $1) ; next };
$2 ~ /^audio/ { system("process_audio_file.sh " $1) ; next };
{ print "$1: unknown file type $2" }'
当然,您必须编写process_video_file.sh
、process_image_file.sh
、 和process_audio_file.sh
脚本。
注意:这将在包含换行符或序列:
(冒号和空格)的文件名上中断,这种情况不太可能但并非不可能遇到。
或者,您可以在 shell 中执行类似的操作:
while read -r f ft ; do
case "$ft" in
video*) process_video_file "$f" ;;
image*) process_image_file "$f" ;;
audio*) process_audio_file "$f" ;;
*) echo "$f: unknown file type $ft" ;;
esac
done < <(file --mime-type * | sed -e 's/: /\t/')
因为这是在 shell 脚本中,所以您可以将“process_(video|image|audio)_file”编写为单独的 shell 脚本或在同一脚本中定义的 shell 函数。您甚至可以将它们内嵌到 case 语句中(但如果每个 case 的语句不止几个,这种方式会导致代码不可读/无法维护)。
注意:这将破坏带有空格、换行符、制表符或与 awk 版本相同的冒号和空格序列的文件名。
重写这个(或 awk 版本)来避免这些文件名问题并不难,但我的回答的目的不是为您编写一个完整的脚本,而是向您展示一些可能的方向自己去解决。
另一种更复杂的替代方法是使用 perl 和几个 perl 模块之一来确定文件的 mime 类型 - 例如文件类型或者文件::MimeInfo。
因为这些都不会在 shell 中,所以您不会遇到任何文件名的 shell 引用或分词问题(即文件名可以包含任何有效字符而不会出现问题)。这不会比使用file
awk 或 shell 做更多的工作或更困难。
如果你想进一步深入了解 perl,perl 还有用于处理多媒体文件元数据的优秀库 - 例如图片::Exiftool(它不仅仅适用于图像文件,不要被名称所迷惑)或视频::信息或者音频::文件。
Perl 甚至还具有与外部音频或视频处理工具和 C 库的接口。具有类似功能的库也可用于 python。这比一个快速而肮脏的脚本需要做更多的工作,后者只是弄清楚它正在处理什么类型的文件并将实际的处理工作交给其他程序,但如果您需要做类似的事情,那么可能值得付出努力这很多,或者需要以现有工具不执行或不按照您需要的方式处理文件。