我正在尝试对我正在处理的项目中的一组特定文件进行符号链接。
我希望符号链接的每个文件名中都有一个已知字符串。
这是我到目前为止所拥有的:
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'