camel

Geekなぺーじ:10のUNIX小技にperlを加えるとさらに幸せになれるというお話。

1.ディレクトリの作成

今時-pをサポートしていないmkdir(1)はないと思いますが、ない場合は

perl -MFile::Path -e 'mkpath $_ for @ARGV' path/to/dir more/path/to/dir ...

で代用が出来ます。

alias mkpath perl -MFile::Path -e \'mkpath \$_ for @ARGV\'

.bashrc.cshrcとしておけば、

mkpath path/to/dir more/path/to/dir ...

と出来ます。

2. tarの解凍先を指定する

応用編として、ディレクトリーの中身を丸ごとコピーする場合にもtarが使えます。

tar cf - . | (cd dest && tar xpf -)

cp(1)などを使った場合、symlinkが実ファイルに置き換えられたり、ownershipやpermissionが変わってしまうことがありますが、これだとメタデータも確実に転写されます。

7. xargsをfind以外と組み合わせる

xargsの代わりに、perlのone-linerと組み合わせる方法もあります。

例:.htmをすべて.htmlに変更
find . -type f -name \*.htm | perl -nle 'rename $_, $_ . "l"'

-nle-pleにすると、ファイル名も一行ごとに表示されるようになります。

さらに、findまでperlにやらせるという方法もあります。

find * -type f -name \*.htm

の代わりに

find2perl . -type f -name \*.htm

とすると、

#! /usr/local/bin/perl -w
    eval 'exec /usr/local/bin/perl -S $0 ${1+"$@"}'
        if 0; #$running_under_some_shell

use strict;
use File::Find ();

# Set the variable $File::Find::dont_use_nlink if you're using AFS,
# since AFS cheats.

# for the convenience of &wanted calls, including -eval statements:
use vars qw/*name *dir *prune/;
*name   = *File::Find::name;
*dir    = *File::Find::dir;
*prune  = *File::Find::prune;

sub wanted;

# Traverse desired filesystems
File::Find::find({wanted => \&wanted}, '.');
exit;

sub wanted {
    my ($dev,$ino,$mode,$nlink,$uid,$gid);

    (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
    -f _ &&
    /^.*\.htm\z/s
    && print("$name\n");
}

という具合にfind(1)互換のperl scriptが標準出力されるので、これを

find2perl . -type f -name \*.htm > whatever.pl

としておいて、あとはwhatever.plを編集します。といっても実際に編集するのは、wanted()の中身だけ。通常のfind(1)ではやりにくい条件分岐なども、ここで簡単に行うことが出来ます。

9. パターンマッチは行全体ではなくフィールドで

perlだと、-aオプションを指定する事でawkっぽい振る舞いをさせることが出来ます。ただしフィールド変数は$数字ではなく、$F[数字]となります。

ls -l | perl -anle 'print if $F[6] eq "Dec"'

Enjoy!

Dan the Perl Monger