递归地“查找”另一个目录中包含字符串和符号链接文件的文件名

递归地“查找”另一个目录中包含字符串和符号链接文件的文件名

我正在尝试对我正在处理的项目中的一组特定文件进行符号链接。

我希望符号链接的每个文件名中都有一个已知字符串。

这是我到目前为止所拥有的:

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

我在目标中设置了目录结构以匹配源,但它只是目录,所以如果更容易为空目标编写命令,我不介意删除这些目录。

更新:

我现在已经接受了一个有效的答案,我想分享一些上下文,以便类似的用例可以更轻松地找到解决方案。

我在 Netbeans 中执行大部分编码。当我为项目构建包时,我倾向于命名所有关联的文件,以便它们具有共同的文件名的一部分。这使我可以在项目中移动时轻松找到自己的包文件。然而,在我当前的项目中,由于涉及大量文件和目录,这非常耗时。

我现在拥有的是为我自己的每个包定义的单独项目,它仅显示该包的文件,同时维护主项目层次结构。

通过构建使用主项目中包文件的符号链接的单独包项目,我有效地创建了我认为是完美的解决方案,而 Netbeans IDE 中似乎没有以当前形式提供的解决方案。

每个子项目什么也不做,只是允许我处理仅与其自身相关的文件子集,这确实使我在键盘上的时间更加高效。

我相信 Eclipse 内置了此功能,尽管我没有 Eclipse。

因此,尽管是一种妥协,但我相信 Netbeans 的这种解决方法是我今天可以实现的最干净的解决方案。这是一个巨大的好处,它的效果也很好,即使没有比我预期的更好。

我原本希望在编辑子项目后运行主项目的手动同步。事实并非如此,master仍然保持自动同步。

答案1

如果您已经在目标位置创建了必要的目录,那么使用find和的 GNU 实现xargs,这并不太困难:

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

输出-printf "%P\0"删除了源目录参数的路径,并以空字节结尾。

xargs然后读取find输出。

-0指示要使用的参数以 null 分隔。

--replace{}告诉 xargs用参数替换(也意味着每个参数运行一个命令)。

最后给出了将参数替换为的命令。

答案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'

相关内容