シェルスクリプトで、特定の名前のファイルを見つけて、そのディレクトリに移動してさらに操作を行うにはどうすればよいですか?
ここから、ファイルを別のディレクトリにコピーします(ただし、コンテキスト用にファイルを追加するだけで、すでにコピーできます)。
次のようなものを使用できます。
_pax[/home/pax]> cd "$(dirname "$(find / -type f -name ls | head -1)")"
pax[/usr/bin]> _
_
これにより、最初のls
通常ファイルが検索され、そのディレクトリに移動します。
各ビットの機能に関して:
/
_から始まり、下に検索して、ls
(_-type f
_)と呼ばれるすべての通常のファイル(_-name ls
_)を一覧表示します。 find
に追加して、取得するファイルをさらに制限できるものは他にもあります。head -1
_を通る配管は、最初のものを除くすべてを除外します。$()
は、コマンドの出力を取得して、anotherコマンドのコマンドラインに配置する方法です。dirname
は完全なファイル指定を取り、パスビットを提供できます。cd
はそのディレクトリに変更するだけです。各ビットを順番に実行すると、何が起こるかがわかります。
_pax[/home/pax]> find / -type f -name ls
/usr/bin/ls
pax[/home/pax]> find / -type f -name ls | head -1
/usr/bin/ls
pax[/home/pax]> dirname "$(find / -type f -name ls | head -1)"
/usr/bin
pax[/home/pax]> cd "$(dirname "$(find / -type f -name ls | head -1)")"
pax[/usr/bin]> _
_
以下の方が安全です。
cd -- "$(find / -name ls -type f -printf '%h' -quit)"
利点:
find
はそのようなファイル名を生成しませんが、有害ではなく、同様の構造に必要な場合があります)-name
前に確認してください-type
チェック。後者にはstat
が必要な場合があるためdirname
は必要ないため、%h
指定子はすでにディレクトリ名を出力します-quit
最初のファイルが見つかった後に検索を停止するため、head
は必要ありません。これにより、改行を含むディレクトリ名でスクリプトが失敗します。見つけることを提案する人は誰もいません(これは巨大な木にとってはるかに速いです)?
zsh:
cd $(locate Zoo.txt|head -1)(:h)
cd ${$(locate Zoo.txt)[1]:h}
cd ${$(locate -r "/Zoo.txt$")[1]:h}
or could be slow
cd **/Zoo.txt(:h)
bash:
cd $(dirname $(locate -l1 -r "/Zoo.txt$"))
同様の質問に対する この回答 に基づいて、他の便利な選択肢は2つのコマンドを使用することです。1つ目はファイルを検索し、2つ目はそのディレクトリに移動します。
find ./ -name "champions.txt"
cd "$(dirname "$(!!)")"
どこ !!
は、「前のコマンド」を意味する履歴拡張です。
find
が見つけて各ディレクトリで操作を実行するすべてのファイルに繰り返しナビゲートしたい場合は、すでに与えられた回答を拡張します。
for i in $(find /path/to/search/root -name filename -type f)
do (
cd $(dirname $(realpath $i));
your_commands;
)
done
ファイルを見つけて別の場所に移動する場合は、findと-execを使用します。
find /path -type f -iname "mytext.txt" -exec mv "{}" /destination +;
function fReturnFilepathOfContainingDirectory {
#fReturnFilepathOfContainingDirectory_2012.0709.18:19
#$1=File
local vlFl
local vlGwkdvlFl
local vlItrtn
local vlPrdct
vlFl=$1
vlGwkdvlFl=`echo $vlFl | gawk -F/ '{ $NF="" ; print $0 }'`
for vlItrtn in `echo $vlGwkdvlFl` ;do
vlPrdct=`echo $vlPrdct'/'$vlItrtn`
done
echo $vlPrdct
}
これを試して。私はこれを自分で使用するために作成しました。
cd ~
touch mycd
Sudo chmod +x mycd
nano mycd
cd $( ./mycd search_directory target_directory )"
if [ $1 == '--help' ]
then
echo -e "usage: cd \$( ./mycd \$1 \$2 )"
echo -e "usage: cd \$( ./mycd search_directory target_directory )"
else
find "$1"/ -name "$2" -type d -exec echo {} \; -quit
fi
単純にこのように、これはエレガントではありませんか?
cdf yourfile.py
もちろん、最初に設定する必要がありますが、これを行う必要があります一度だけ:
シェル初期化スクリプトとして使用するものは何でも、.bashrcまたは.zshrcに次の行を追加します。
source ~/bin/cdf.sh
そして、このコードを、最初から作成する必要がある〜/ bin /cdf.shファイルに追加します。
#!/bin/bash
function cdf() {
THEFILE=$1
echo "cd into directory of ${THEFILE}"
# For Mac, replace find with mdfind to get it a lot faster. And it does not need args ". -name" part.
THEDIR=$(find . -name ${THEFILE} |head -1 |grep -Eo "/[ /._A-Za-z0-9\-]+/")
cd ${THEDIR}
}
PATH
内のプログラムの場合は、次のことができます。
cd "$(dirname "$(which ls)")"
またはBashで:
cd "$(dirname "$(type -P ls)")"
使用する外部実行可能ファイルが1つ少なくなります。
これは外部を使用しません:
dest=$(type -P ls); cd "${dest%/*}"
ファイルが1つの場所にのみある場合は、次のことを試すことができます。
cd "$(find ~/ -name [filename] -exec dirname {} \;)" && ...
_-exec
_を使用して、returnを見つけるパス(_{}
_プレースホルダーがある場所)でdirname
を呼び出すことができます。それはディレクトリを変更します。シェルがディレクトリを変更した後、次のコマンドを実行するためにダブルアンパサンド(_&&
_)を追加することもできます。
例えば:cd "$(find ~/ -name need_to_find_this.rb -exec dirname {} \;)" && Ruby need_to_find_this.rb
そのRubyファイルを探し、ディレクトリに移動して、そのフォルダ内から実行します。この例では、ファイル名は一意であり、何らかの理由でRubyスクリプトはそのディレクトリ内から実行する必要があります。ファイル名が一意でない場合、CDに渡される多くの場所を取得し、エラーを返します変更されませんディレクトリ。