ファイルへの文字列とシンボリックリンクを含む他のディレクトリでファイル名を繰り返し「検索」

ファイルへの文字列とシンボリックリンクを含む他のディレクトリでファイル名を繰り返し「検索」

私が作業しているプロジェクトで特定のファイルセットをシンボリックリンクしようとしています。

各ファイル名に既知の文字列を含むシンボリックリンクが必要です。

これが私が今まで持っているものです:

ln -s find ~/path/to/src/ -name "*stringtomatch*" find ~/path/to/dest

ソースと一致するようにターゲットにディレクトリ構造を設定しましたが、これはディレクトリにすぎないため、空のターゲットのコマンドを作成する方が簡単な場合は、そのディレクトリを削除してもかまいません。

修正する:

今、私は有効な答えを受け入れました、そして同様のユースケースでより簡単に解決策を見つけるためにいくつかのコンテキストを共有したいと思います。

私はほとんどのコーディングをNetbeansで行います。私はプロジェクト用のパッケージを作成するときにファイル名の共通部分を持つようにすべての関連ファイルの名前を付ける傾向があります。これにより、プロジェクトを移動するときにパッケージファイルを簡単に見つけることができます。しかし、現在のプロジェクトでは、関連するファイルとディレクトリの数が多いため、時間がかかります。

今私が持っているのは、基本的なプロジェクト階層を維持しながらそのパッケージのファイルのみを表示する各パッケージに対して定義された別々のプロジェクトです。

メインプロジェクトのパッケージファイルへのシンボリックリンクを使用する別のパッケージプロジェクトを構築することで、私はNetbeans IDEで現在の形式では利用できない完璧なソリューションだと思うソリューションを効果的にしました。

各サブプロジェクトは何もしませんが、それ自体にのみ関連するファイルのサブセットを操作できるようにするので、実際にキーボードの使用時間がより効率的になります。

私はEclipseを持っていませんが、Eclipseにこの機能が組み込まれていると思います。

したがって、トレードオフですが、私はこのNetbeansの解決策が私が今日実装できる最もきれいなソリューションであると信じています。これは大きな利点であり、予想より良くない場合でもうまく機能します。

もともとサブプロジェクトを編集した後、メインプロジェクトの手動同期を実行したかったのです。そうでない場合、マスターはまだ自動的に同期状態を維持します。

答え1

findGNU実装を使用することはxargsそれほど難しくなく、ターゲットの場所に必要なディレクトリをすでに作成している場合:

find ~/path/to/src -name "*stringtomatch*" -printf "%P\0" |
  xargs -r0 --replace ln -s ~/path/to/src/'{}' ~/path/to/dest/'{}'

出力には、-printf "%P\0"ソースディレクトリパラメータへのパスが削除され、nullバイトで終了します。

xargsfindその後、出力を読みます。

-0使用するパラメータをnullで区切って表します。

--replace{}xargsに引数で置き換えるように指示します(引数ごとに1つのコマンドを実行するという意味でもあります)。

最後に、パラメータを置き換えるコマンドが提供されます。

答え2

このために短いスクリプトを作成しました。素晴らしい出力が出てくるので、結果を簡単に確認できます。宛先ディレクトリ構造を作成する必要はありません。使用方法:

$ ./recursive-symlink.sh --help
Usage:
  ./recursive-symlink.sh <source_path> <dest_path> <find_args...>

使い方を示すために、最初に次のファイル/ディレクトリがあるとしましょう。

├── recursive-symlink.sh*
└── src/
    ├── dir1/
    │   ├── file_A_misc.txt
    │   └── file_B_sub.txt
    ├── dir3/
    │   ├── file_A3.txt
    │   ├── file_C.txt
    │   └── subsub_dir/
    │       ├── file_Asubsub.txt
    │       └── file_D.txt
    ├── dir_A/
    │   └── should_be_empty.dat
    ├── file_A.txt
    └── file_B.txt

私が実行した場合:

$ find -name '*_A*'
./src/file_A.txt
./src/dir3/file_A3.txt
./src/dir3/subsub_dir/file_Asubsub.txt
./src/dir_A
./src/dir1/file_A_misc.txt

どのファイルがリンクされているかがわかります。次に、次のようにスクリプトを実行します。

$ ./recursive-symlink.sh src/ dest/ -name '*_A*'
src/file_A.txt
mkdir: created directory 'dest'
'dest/file_A.txt' -> '../src/file_A.txt'

src/dir3/file_A3.txt
mkdir: created directory 'dest/dir3'
'dest/dir3/file_A3.txt' -> '../../src/dir3/file_A3.txt'

src/dir3/subsub_dir/file_Asubsub.txt
mkdir: created directory 'dest/dir3/subsub_dir'
'dest/dir3/subsub_dir/file_Asubsub.txt' -> '../../../src/dir3/subsub_dir/file_Asubsub.txt'

src/dir_A
'dest/dir_A' -> '../src/dir_A'

src/dir1/file_A_misc.txt
mkdir: created directory 'dest/dir1'
'dest/dir1/file_A_misc.txt' -> '../../src/dir1/file_A_misc.txt'

私の最終状態は次のとおりです。

├── recursive-symlink.sh*
├── src/
│   ├── dir1/
│   │   ├── file_A_misc.txt
│   │   └── file_B_sub.txt
│   ├── dir3/
│   │   ├── file_A3.txt
│   │   ├── file_C.txt
│   │   └── subsub_dir/
│   │       ├── file_Asubsub.txt
│   │       └── file_D.txt
│   ├── dir_A/
│   │   └── should_be_empty.dat
│   ├── file_A.txt
│   └── file_B.txt
└── dest/
    ├── dir1/
    │   └── file_A_misc.txt -> ../../src/dir1/file_A_misc.txt
    ├── dir3/
    │   ├── file_A3.txt -> ../../src/dir3/file_A3.txt
    │   └── subsub_dir/
    │       └── file_Asubsub.txt -> ../../../src/dir3/subsub_dir/file_Asubsub.txt
    ├── dir_A -> ../src/dir_A/
    └── file_A.txt -> ../src/file_A.txt

destすべての再帰サブディレクトリとともに、ディレクトリが自動的に作成され、そのディレクトリ内のパターンと一致するファイルのみがdestリンクされていることがわかります。*_A*


スクリプトのソースコードは次のとおりです。

#!/bin/bash

verbose='-v'  # you may comment this line

if [ "$1" == '-h' ] || [ "$1" == '--help' ] || [ $# -lt 3 ]
then
    echo "Usage:"
    echo "  $0 <source_path> <dest_path> <find_args...>"
    exit
fi

src="${1%/}" ; shift
dest="${1%/}" ; shift
relflag='' ; [ "${src:0:1}" != '/' ] && relflag='-r'

find "$src" \( "$@" \) -print0 |
    while IFS= read -r -d '' f
    do
        base_fname="${f#$src}"
        [ "$verbose" ] && echo "${f}"
        dest_ln="$dest/${base_fname#/}"
        dest_dir="$(dirname "$dest_ln")"
        mkdir -p $verbose "$dest_dir"
        ln $relflag -s $verbose -t "$dest_dir" "$f"
        [ "$verbose" ] && echo
    done

答え3

使用zsh(ターゲットディレクトリがすでに存在すると仮定):

autoload zmv # best in ~/.zshrc
zmv -Ls ~/path/to/src/'(**/)(*stringtomatch*)' ~/path/to/dst/'$1$2'

ln実装がGNU実装の場合は、その-rオプションを使用して相対シンボリックリンクを生成できます(ここにも-v適用されます)。言葉が多い)。

zmv -Ls -o-rv ~/path/to/src/'(**/)(*stringtomatch*)' ~/path/to/dst/'$1$2'

関連情報