web-dev-qa-db-ja.com

検索コマンドのベース名で実行します

次のようなディレクトリ構造があるとします。

test
test/a
test/b

ここで、.フォルダーで、ファイルaおよびbのベース名でコマンドを実行できるようにコマンドを実行します。

だから基本的にはこういうものが欲しいので素朴にやってみました

find test -type f -exec touch `basename {}` \;

ただ、これによって親ディレクトリに空のファイルabが作成されることはありません。私のtouchコマンドが取ることができる引数は1つだけだとします。

これにより、次のようなディレクトリ構造になります。

a
b
test
test/a
test/b

私はbashスクリプトでこれを行う方法を知っていますが、単一のコマンドソリューションに興味があります。

3
Bernhard

execdirfindオプションを試してください。引数としてベース名のみを使用して、ファイルのディレクトリで指定したコマンドを実行します。

私が集めたものから、あなたは「メイン」ディレクトリに「a」と「b」を作成したいと思います。これは、$PWDオプションと-execdirオプションを組み合わせることで実現できます。以下の解決策をご覧ください。 (&& find … lsの部分は出力専用なので、効果を確認できます。&&の前にコマンドを使用することをお勧めします。)

まず、テスト環境を設定します。

-----[ 15:40:17 ] (!6293) [ :-) ] janmoesen@mail ~/stack 
$ mkdir test && touch test/{a,b} && find . -exec ls -dalF {} +
drwxr-xr-x 3 janmoesen janmoesen 4096 2012-05-31 15:40 ./
drwxr-xr-x 2 janmoesen janmoesen 4096 2012-05-31 15:40 ./test/
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:40 ./test/a
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:40 ./test/b

これは、単純な-execを使用した場合に発生します—元のファイルが変更されます。

-----[ 15:40:30 ] (!6294) [ :-) ] janmoesen@mail ~/stack 
$ find test -type f -exec touch {} \; && find . -exec ls -dalF {} +
drwxr-xr-x 3 janmoesen janmoesen 4096 2012-05-31 15:40 ./
drwxr-xr-x 2 janmoesen janmoesen 4096 2012-05-31 15:40 ./test/
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:40 ./test/a
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:40 ./test/b

ただし、$PWDを引数プレースホルダー{}と組み合わせて-execdirを使用すると、(私が思うに)必要なものが得られます。

-----[ 15:40:57 ] (!6295) [ :-) ] janmoesen@mail ~/stack 
$ find test -type f -execdir touch "$PWD/{}" \; && find . -exec ls -dalF {} +
drwxr-xr-x 3 janmoesen janmoesen 4096 2012-05-31 15:41 ./
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:41 ./a
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:41 ./b
drwxr-xr-x 2 janmoesen janmoesen 4096 2012-05-31 15:40 ./test/
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:40 ./test/a
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:40 ./test/b
1
janmoesen

Bashを実行します。

find ... -exec bash -c 'touch "${1##*/}"' btouch {} \;

ここで、${1##*/}は、/で終わる2番目の引数から最長の一致を削除し、最後の/以降のすべてを保持することを意味します。

btouchは、アクティブなプロセスリストに正しく表示されるように、任意のダミー名にすることができます(ps

ご自身の責任でこれを試してください:

find test -type f -exec echo touch \"\$\(basename "'{}'"\)\" \; | bash

スペースを含むファイル名でテストされています。

3
AndresVia

シェルを呼び出して、パスで文字列処理を少し実行します。 ${VARIABLE##PATTERN}文字列操作構造を使用して、PATTERNからVARIABLEに一致するプレフィックスを削除できます—パターン*/は先頭のディレクトリ名を削除します。

find test -type f -exec sh -c 'for x; do touch "${x##*/}"; done' _ {} +

GNU findを使用する別の方法は、サブディレクトリに変更することです。シェルを呼び出して、元のディレクトリに戻します。

find test -type f -execdir sh -c 'cd "$0" && touch -- "$@"' "$PWD" {} +

または、findを削除してzshを使用します。具体的には、t履歴修飾子グロブ修飾子 として追加します。

touch test/**/*(:t)

これはどう?

$ touch $(find test -type f -exec basename {} \;)
1
Abhishek A