22242


諸事情により、特定のディレクトリの中の、実行権限がすべて吹っ飛んでしまいました; すべて 664 のパーミッションになっています。

このディレクトリには、実行可能(だったはずの)シェルスクリプトと、 windows 用の .bat ファイルが混合しています。

この状態で、実行可能だったはずのシェルスクリプトすべてに実行権限を付与したいと考えています。具体的には、実行可能だったシェルスクリプトは、すべて
shebang が #!/bin/sh だったので、これらに対して chmod を実行したいのですが、これを、なるべく簡単に実現する方法はありますか？


CC BY-SA 3.0
2016-02-18T13:07:14.773
22241
2016-02-19T10:26:45.210
754
question
unix
unix で、 特定のディレクトリで、 shebang が /bin/sh のものだけ実行権限を付与したい


`file`コマンドでファイルの種類を調べられます。手元の環境ですと

[code]

    $ file -bi bin/some.sh
    text/x-shellscript; charset=us-ascii
    
[/code]

という出力を得られますので、この文字列が含まれるか`grep`で判定できます。

[code]

    $ file -bi bin/some.sh | grep -q 'text/x-shellscript' && echo "shell script!"
    shell script!
    
[/code]

あとはこれをループしてやればいいでしょう。

[code]

    $ for f in somedir/*; do file -bi "$f" | grep -q 'text/x-shellscript' && echo chmod +x "$f"; done
    chmod +x bin/some.sh
    ...
    
[/code]

問題なさそうなら`echo`を消せば`chmod`が実行されます。


CC BY-SA 3.0
2016-02-18T13:26:13.280
22242
2016-02-19T10:26:45.210
2016-02-19T10:26:45.210
754
4236
22241
answer


以下は find と GNU grep を使う方法です。

[code]

    $ find [target_dir] -type f -exec grep -PlZs '\A#!/bin/sh' {} \+ | xargs -0 chmod +x
    
[/code]

GNU grep の `-P` オプション(Perl 互換の正規表現が使用可能)における `\A`
はファイルの先頭にマッチする正規表現です。また、この場合は `[target_dir]`
以降の全ての通常ファイルが対象になりますので、`[target_dir]` 内のファイルだけを対象にしたい場合は find に `-maxdepth 1`
を付ける必要があるかもしれません。

※ Linux distribution では GNU grep がデフォルトかと思いますが、UNIX 系 OS ではオプショナルでしょうから、`unix`
カテゴリからは外れている回答かもしれません


CC BY-SA 3.0
2016-02-18T14:40:18.243
22244
2016-02-18T14:40:18.243
22241
answer


どこにでもある sed と test を使うとこう書けます。

[code]

    for f in your_dir/*; do s=`sed '-e /^#!\\/bin\\/sh$/!x' -eq "$f"` && if [ "$s" ]; then chmod +x "$f"; fi; done
    
[/code]

sed のコマンドですが、エスケープシーケンスを解除すると `-e /^#!\/bin\/sh$/!x`, `-eq` になります。  
一つ目で正規表現 `/^#!\/bin\/sh$/` により shebang
にマッチさせ、マッチしなければホールドスペース(初期状態は空)とパターンスペースを入れ替える。  
二つ目で評価を即座に終了します。  
つまり、一行目の shebang のみがパターンスペースに残ります。

適当に改行を入れると少しわかりやすくなります。

[code]

    for f in your_dir/*
    do  s=`sed '-e /^#!\\/bin\\/sh$/!x' -eq "$f"` && \
        if [ "$s" ]
        then chmod +x "$f"
        fi
    done
    
[/code]


CC BY-SA 3.0
2016-02-19T03:08:07.387
22257
2016-02-19T03:08:07.387
8431
22241
answer