複数のファイルを含むディレクトリがあり、その一部はbashスクリプトですが、ファイル名に.sh拡張子が含まれていません。 -typeオプションを使用してファイル形式を確認するには、fileコマンドを使用する必要があること、およびxargsを使用して出力をリダイレクトしてファイル名を元の名前+ .sh拡張子に変更できることもわかります。問題は、すべてのコマンドを一緒にリンクする方法、またはbash ASCIIテキスト専用の実行可能ファイルのファイル形式を見つける方法がわからないことです。簡単なコマンドでこれを行う方法を知っていますか?
答え1
標準のshebangラインを設定するとfile
(最小バージョン5.39)、これを検出できるはずです。
$ echo '#!/usr/bin/env bash' > 1
$ echo '#!/bin/bash' > 2
$ echo '#!/usr/bin/bash' > 3
$ file *
1: Bourne-Again shell script, ASCII text executable
2: Bourne-Again shell script, ASCII text executable
3: Bourne-Again shell script, ASCII text executable
だから私たちはこれを行うことができなければなりません:
for path in ./*
do
if [[ "$(file "$path")" = "${path}: Bourne-Again shell script, ASCII text executable" ]]
then
mv "$path" "${path}.bash"
fi
done
これは上記のサンプルファイルで機能します(そして、空白文字を含むか、ハイフンで始まる、または改行文字で終わるファイル名を含む珍しいファイル名でも機能する必要があります)。
$ ls
1.bash 2.bash 3.bash
これはおそらくいいえこれは、ファイルにshebang行がない場合に機能します(これは次のファイルに適しています)。他のスクリプトから取得またはshebang行が正しくありません(例:#!/bin/sh
)。
(私は「.sh」よりも明示的なので、「.bash」を使用しました。)
答え2
find
これは何もしませんが、kannがgrep
ファイルディレクトリを再帰的に取得する必要はありません-r
(ファイル名がワイルドカードを介して渡される場合でも)。
grep -lIw '^#!.*bash' dir/!(*.sh) | xargs -I_ mv _ _.sh
grep-r
目次すべてのサブディレクトリ内のすべてのファイルを検索します(ここでは使用されません)。
grepは一致する各ファイル名を印刷する-l
のと似ています-H
が、通常の出力を抑制します。また、最初の一致の後、-q
または同様に停止します。-m1
grepは-I
バイナリファイルを除いてテキストファイルのみを処理します。
grep-w
強く打つ完全な単語だけが一致します(一致しません)。強く打つ編集する)
正規表現^
#!行の先頭のみが一致します(#と一致しません)。#!)
すべてのバイト=すべての文字列.
に一致する正規表現*
.*
パス名拡張(ワイルドカード)が*.sh
file.shパターンと一致します。
拡張ワイルドカードは、!(pattern)
パターンを除くすべての項目と一致します。
lsはdir/!(*.sh)
すべてのファイルをリストします目次入らないようにするディレクトリ/file.sh文書
パラメータ-I
模様パラメータは各位置に挿入されます。模様_
この例では、次を使用します。
mv _ _ .sh
mv file1 file1.sh
mv file2 file2.sh