Recursively “find” file names containing string and symlink files in another directoryHow to find files containing two strings in different linesbash find: get directory of found fileSymlink files to mirrored directory treeFind Directory if Number of files is over XHow to find files and act on them (find + exec)Make `rsync --link-dest` find files recursivelyunpacking recursively all xlsx files into a new directory containing of the original files nameFind and Replace Colours in CSS Files from Command LineFind and delete files, whilst keeping any matching files if in a specific directoryHow to rename a file to have the same name and extension as another file in same directory
How to compare two different formulations of a problem?
Have only girls been born for a long time in this village?
Was Tuvok bluffing when he said that Voyager's transporters rendered the Kazon weapons useless?
What professions would a medieval village with a population of 100 need?
Does C++20 mandate source code being stored in files?
Are there nouns that change meaning based on gender?
Thread-safe, Convenient and Performant Random Number Generator
Running script line by line automatically yet being asked before each line from second line onwards
jersey vs sweater
How to "know" if I have a passion?
To "hit home" in German
Designing a prison for a telekinetic race
(Why) May a Beit Din refuse to bury a body in order to coerce a man into giving a divorce?
How to dismiss intrusive questions from a colleague with whom I don't work?
How can I run SQL Server Vulnerability Assessment from a SQL Job?
Are there any plans for handling people floating away during an EVA?
Are illustrations in novels frowned upon?
How to determine if an Apex class hasn't been used recently
Can pay be witheld for hours cleaning up after closing time?
In an emergency, how do I find and share my position?
Why doesn't mathematics collapse even though humans quite often make mistakes in their proofs?
Can a group have a cyclical derived series?
What does it mean to have a subnet mask /32?
!I!n!s!e!r!t! !n!b!e!t!w!e!e!n!
Recursively “find” file names containing string and symlink files in another directory
How to find files containing two strings in different linesbash find: get directory of found fileSymlink files to mirrored directory treeFind Directory if Number of files is over XHow to find files and act on them (find + exec)Make `rsync --link-dest` find files recursivelyunpacking recursively all xlsx files into a new directory containing of the original files nameFind and Replace Colours in CSS Files from Command LineFind and delete files, whilst keeping any matching files if in a specific directoryHow to rename a file to have the same name and extension as another file in same directory
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I am trying to symlink a set of specific files from a project I'm working on.
There is a known string in each of the filenames I wish to symlink.
Here is what I have so far:
ln -s find ~/path/to/src/ -name "*stringtomatch*" find ~/path/to/dest
I have the directory structure setup in the destination to match the source, but it's just directories, so I don't mind deleting those if it's easier to write a command that for an empty destination.
Update:
I have now accepted a working answer and I want to share some context so that a similar use case might find a solution more easily.
I perform the majority of my coding in Netbeans. When I am building packages for a project I tend to name all of the associated files so that they have part of the file name in common. This allows me to easily find my own package files as I move around within the project. However in my current project this is very time consuming due to the large volume of files and directories involved.
What I have now is a separate project defined for each of my own packages which show only the files for that package while maintaining the master project hierarchy.
By building separate package projects that use symlinks to my package files within the master project, I have effectively created what I believe to be the perfect solution where there doesn't seem to be one available within the Netbeans IDE in its current form.
Each sub-project does nothing but allow me to work on a subset of files relating only to itself which really makes my time at the keyboard more efficient.
I believe Eclipse has this feature in-built, though I do not have Eclipse.
So, albeit a compromise I believe that this workaround for Netbeans is as clean a solution I could achieve today. It's a huge bonus that it works as well, if not better than I had anticipated.
I had expected to run manual synchronisations of the master after edits to the sub-projects. This is not the case, the master still maintains automatic synchronisation.
find symlink ln
add a comment |
I am trying to symlink a set of specific files from a project I'm working on.
There is a known string in each of the filenames I wish to symlink.
Here is what I have so far:
ln -s find ~/path/to/src/ -name "*stringtomatch*" find ~/path/to/dest
I have the directory structure setup in the destination to match the source, but it's just directories, so I don't mind deleting those if it's easier to write a command that for an empty destination.
Update:
I have now accepted a working answer and I want to share some context so that a similar use case might find a solution more easily.
I perform the majority of my coding in Netbeans. When I am building packages for a project I tend to name all of the associated files so that they have part of the file name in common. This allows me to easily find my own package files as I move around within the project. However in my current project this is very time consuming due to the large volume of files and directories involved.
What I have now is a separate project defined for each of my own packages which show only the files for that package while maintaining the master project hierarchy.
By building separate package projects that use symlinks to my package files within the master project, I have effectively created what I believe to be the perfect solution where there doesn't seem to be one available within the Netbeans IDE in its current form.
Each sub-project does nothing but allow me to work on a subset of files relating only to itself which really makes my time at the keyboard more efficient.
I believe Eclipse has this feature in-built, though I do not have Eclipse.
So, albeit a compromise I believe that this workaround for Netbeans is as clean a solution I could achieve today. It's a huge bonus that it works as well, if not better than I had anticipated.
I had expected to run manual synchronisations of the master after edits to the sub-projects. This is not the case, the master still maintains automatic synchronisation.
find symlink ln
1
I've deleted my answer, since I'm still working on to find how to preserve the path in the destination
– Inian
Aug 8 at 7:38
add a comment |
I am trying to symlink a set of specific files from a project I'm working on.
There is a known string in each of the filenames I wish to symlink.
Here is what I have so far:
ln -s find ~/path/to/src/ -name "*stringtomatch*" find ~/path/to/dest
I have the directory structure setup in the destination to match the source, but it's just directories, so I don't mind deleting those if it's easier to write a command that for an empty destination.
Update:
I have now accepted a working answer and I want to share some context so that a similar use case might find a solution more easily.
I perform the majority of my coding in Netbeans. When I am building packages for a project I tend to name all of the associated files so that they have part of the file name in common. This allows me to easily find my own package files as I move around within the project. However in my current project this is very time consuming due to the large volume of files and directories involved.
What I have now is a separate project defined for each of my own packages which show only the files for that package while maintaining the master project hierarchy.
By building separate package projects that use symlinks to my package files within the master project, I have effectively created what I believe to be the perfect solution where there doesn't seem to be one available within the Netbeans IDE in its current form.
Each sub-project does nothing but allow me to work on a subset of files relating only to itself which really makes my time at the keyboard more efficient.
I believe Eclipse has this feature in-built, though I do not have Eclipse.
So, albeit a compromise I believe that this workaround for Netbeans is as clean a solution I could achieve today. It's a huge bonus that it works as well, if not better than I had anticipated.
I had expected to run manual synchronisations of the master after edits to the sub-projects. This is not the case, the master still maintains automatic synchronisation.
find symlink ln
I am trying to symlink a set of specific files from a project I'm working on.
There is a known string in each of the filenames I wish to symlink.
Here is what I have so far:
ln -s find ~/path/to/src/ -name "*stringtomatch*" find ~/path/to/dest
I have the directory structure setup in the destination to match the source, but it's just directories, so I don't mind deleting those if it's easier to write a command that for an empty destination.
Update:
I have now accepted a working answer and I want to share some context so that a similar use case might find a solution more easily.
I perform the majority of my coding in Netbeans. When I am building packages for a project I tend to name all of the associated files so that they have part of the file name in common. This allows me to easily find my own package files as I move around within the project. However in my current project this is very time consuming due to the large volume of files and directories involved.
What I have now is a separate project defined for each of my own packages which show only the files for that package while maintaining the master project hierarchy.
By building separate package projects that use symlinks to my package files within the master project, I have effectively created what I believe to be the perfect solution where there doesn't seem to be one available within the Netbeans IDE in its current form.
Each sub-project does nothing but allow me to work on a subset of files relating only to itself which really makes my time at the keyboard more efficient.
I believe Eclipse has this feature in-built, though I do not have Eclipse.
So, albeit a compromise I believe that this workaround for Netbeans is as clean a solution I could achieve today. It's a huge bonus that it works as well, if not better than I had anticipated.
I had expected to run manual synchronisations of the master after edits to the sub-projects. This is not the case, the master still maintains automatic synchronisation.
find symlink ln
find symlink ln
edited Aug 8 at 19:58
Chris
asked Aug 8 at 7:08
ChrisChris
1185 bronze badges
1185 bronze badges
1
I've deleted my answer, since I'm still working on to find how to preserve the path in the destination
– Inian
Aug 8 at 7:38
add a comment |
1
I've deleted my answer, since I'm still working on to find how to preserve the path in the destination
– Inian
Aug 8 at 7:38
1
1
I've deleted my answer, since I'm still working on to find how to preserve the path in the destination
– Inian
Aug 8 at 7:38
I've deleted my answer, since I'm still working on to find how to preserve the path in the destination
– Inian
Aug 8 at 7:38
add a comment |
3 Answers
3
active
oldest
votes
I created a short script to do this, with a nice output which should be easy check the results. It doesn't need to have the destination directory structure created. Use as follows:
$ ./recursive-symlink.sh --help
Usage:
./recursive-symlink.sh <source_path> <dest_path> <find_args...>
To show its usage, let's say I have the following files/dirs at the begining:
├── 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
If I run:
$ 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
I can see which files would be linked. I then run the script like this:
$ ./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'
My final state will be then:
├── 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
You can see that dest directory is created automatically, as well all recursive subdirectories, and on the dest dir, only the files that matched the *_A* pattern were linked.
Here the script source code:
#!/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
I don't know that this is the best answer, but i do like the script option because it means all i need to do is read a comment in the file and I can remember exactly how to use it in the future. So thank you, for that reason I have accepted your answer.
– Chris
Aug 8 at 17:42
1
Hi @Chris, thanks, that's actually why I do lots of utility scripts, even if they are just a couple lines, it's common to have the same problems over and over again, and sometimes, even for just a one-liner, you end up spending some fair amount of time to get it right, I usually do those directly on the interactive shell and when they are working, I put on a file, parametrize them a bit and add a "Usage: " help. Months later this saves me many hours of re-work..
– Fabiano
Aug 8 at 20:41
This one for example I also started as a one-liner, similar to @wurtel's (but four commands instead of three:find,while,lnplus the additionalmkdir), the rest is just some boiler plate to treat corner cases (like filenames with exotic chars such asn, handle both absolute and relative paths, verbosity, accept multiple parameters to the find, etc) and then it becomes pretty hard to read and understand a few days later..
– Fabiano
Aug 8 at 20:42
add a comment |
If you already have the necessary directories created in the target location, then with the GNU implementations of find and xargs, it's not too difficult:
find ~/path/to/src -name "*stringtomatch*" -printf "%P" |
xargs -r0 --replace ln -s ~/path/to/src/'' ~/path/to/dest/''
The -printf "%P" outputs the path with the source directory parameter removed, and ends with a null byte.
xargs then reads the find output.
-0 indicates the parameters to use are null-separated.
--replace tells xargs to replace with the argument (also implies running one command per argument).
Finally the command to replace arguments into is given.
the%Pis very neat!!
– Fabiano
Aug 8 at 20:44
add a comment |
With zsh (assuming the target directories already exist):
autoload zmv # best in ~/.zshrc
zmv -Ls ~/path/to/src/'(**/)(*stringtomatch*)' ~/path/to/dst/'$1$2'
If your ln implementation is the GNU one, you can use its -r option to make relative symlinks (here also -v for verbose).
zmv -Ls -o-rv ~/path/to/src/'(**/)(*stringtomatch*)' ~/path/to/dst/'$1$2'
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f534489%2frecursively-find-file-names-containing-string-and-symlink-files-in-another-dir%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
I created a short script to do this, with a nice output which should be easy check the results. It doesn't need to have the destination directory structure created. Use as follows:
$ ./recursive-symlink.sh --help
Usage:
./recursive-symlink.sh <source_path> <dest_path> <find_args...>
To show its usage, let's say I have the following files/dirs at the begining:
├── 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
If I run:
$ 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
I can see which files would be linked. I then run the script like this:
$ ./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'
My final state will be then:
├── 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
You can see that dest directory is created automatically, as well all recursive subdirectories, and on the dest dir, only the files that matched the *_A* pattern were linked.
Here the script source code:
#!/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
I don't know that this is the best answer, but i do like the script option because it means all i need to do is read a comment in the file and I can remember exactly how to use it in the future. So thank you, for that reason I have accepted your answer.
– Chris
Aug 8 at 17:42
1
Hi @Chris, thanks, that's actually why I do lots of utility scripts, even if they are just a couple lines, it's common to have the same problems over and over again, and sometimes, even for just a one-liner, you end up spending some fair amount of time to get it right, I usually do those directly on the interactive shell and when they are working, I put on a file, parametrize them a bit and add a "Usage: " help. Months later this saves me many hours of re-work..
– Fabiano
Aug 8 at 20:41
This one for example I also started as a one-liner, similar to @wurtel's (but four commands instead of three:find,while,lnplus the additionalmkdir), the rest is just some boiler plate to treat corner cases (like filenames with exotic chars such asn, handle both absolute and relative paths, verbosity, accept multiple parameters to the find, etc) and then it becomes pretty hard to read and understand a few days later..
– Fabiano
Aug 8 at 20:42
add a comment |
I created a short script to do this, with a nice output which should be easy check the results. It doesn't need to have the destination directory structure created. Use as follows:
$ ./recursive-symlink.sh --help
Usage:
./recursive-symlink.sh <source_path> <dest_path> <find_args...>
To show its usage, let's say I have the following files/dirs at the begining:
├── 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
If I run:
$ 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
I can see which files would be linked. I then run the script like this:
$ ./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'
My final state will be then:
├── 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
You can see that dest directory is created automatically, as well all recursive subdirectories, and on the dest dir, only the files that matched the *_A* pattern were linked.
Here the script source code:
#!/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
I don't know that this is the best answer, but i do like the script option because it means all i need to do is read a comment in the file and I can remember exactly how to use it in the future. So thank you, for that reason I have accepted your answer.
– Chris
Aug 8 at 17:42
1
Hi @Chris, thanks, that's actually why I do lots of utility scripts, even if they are just a couple lines, it's common to have the same problems over and over again, and sometimes, even for just a one-liner, you end up spending some fair amount of time to get it right, I usually do those directly on the interactive shell and when they are working, I put on a file, parametrize them a bit and add a "Usage: " help. Months later this saves me many hours of re-work..
– Fabiano
Aug 8 at 20:41
This one for example I also started as a one-liner, similar to @wurtel's (but four commands instead of three:find,while,lnplus the additionalmkdir), the rest is just some boiler plate to treat corner cases (like filenames with exotic chars such asn, handle both absolute and relative paths, verbosity, accept multiple parameters to the find, etc) and then it becomes pretty hard to read and understand a few days later..
– Fabiano
Aug 8 at 20:42
add a comment |
I created a short script to do this, with a nice output which should be easy check the results. It doesn't need to have the destination directory structure created. Use as follows:
$ ./recursive-symlink.sh --help
Usage:
./recursive-symlink.sh <source_path> <dest_path> <find_args...>
To show its usage, let's say I have the following files/dirs at the begining:
├── 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
If I run:
$ 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
I can see which files would be linked. I then run the script like this:
$ ./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'
My final state will be then:
├── 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
You can see that dest directory is created automatically, as well all recursive subdirectories, and on the dest dir, only the files that matched the *_A* pattern were linked.
Here the script source code:
#!/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
I created a short script to do this, with a nice output which should be easy check the results. It doesn't need to have the destination directory structure created. Use as follows:
$ ./recursive-symlink.sh --help
Usage:
./recursive-symlink.sh <source_path> <dest_path> <find_args...>
To show its usage, let's say I have the following files/dirs at the begining:
├── 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
If I run:
$ 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
I can see which files would be linked. I then run the script like this:
$ ./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'
My final state will be then:
├── 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
You can see that dest directory is created automatically, as well all recursive subdirectories, and on the dest dir, only the files that matched the *_A* pattern were linked.
Here the script source code:
#!/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
answered Aug 8 at 10:22
FabianoFabiano
1461 bronze badge
1461 bronze badge
I don't know that this is the best answer, but i do like the script option because it means all i need to do is read a comment in the file and I can remember exactly how to use it in the future. So thank you, for that reason I have accepted your answer.
– Chris
Aug 8 at 17:42
1
Hi @Chris, thanks, that's actually why I do lots of utility scripts, even if they are just a couple lines, it's common to have the same problems over and over again, and sometimes, even for just a one-liner, you end up spending some fair amount of time to get it right, I usually do those directly on the interactive shell and when they are working, I put on a file, parametrize them a bit and add a "Usage: " help. Months later this saves me many hours of re-work..
– Fabiano
Aug 8 at 20:41
This one for example I also started as a one-liner, similar to @wurtel's (but four commands instead of three:find,while,lnplus the additionalmkdir), the rest is just some boiler plate to treat corner cases (like filenames with exotic chars such asn, handle both absolute and relative paths, verbosity, accept multiple parameters to the find, etc) and then it becomes pretty hard to read and understand a few days later..
– Fabiano
Aug 8 at 20:42
add a comment |
I don't know that this is the best answer, but i do like the script option because it means all i need to do is read a comment in the file and I can remember exactly how to use it in the future. So thank you, for that reason I have accepted your answer.
– Chris
Aug 8 at 17:42
1
Hi @Chris, thanks, that's actually why I do lots of utility scripts, even if they are just a couple lines, it's common to have the same problems over and over again, and sometimes, even for just a one-liner, you end up spending some fair amount of time to get it right, I usually do those directly on the interactive shell and when they are working, I put on a file, parametrize them a bit and add a "Usage: " help. Months later this saves me many hours of re-work..
– Fabiano
Aug 8 at 20:41
This one for example I also started as a one-liner, similar to @wurtel's (but four commands instead of three:find,while,lnplus the additionalmkdir), the rest is just some boiler plate to treat corner cases (like filenames with exotic chars such asn, handle both absolute and relative paths, verbosity, accept multiple parameters to the find, etc) and then it becomes pretty hard to read and understand a few days later..
– Fabiano
Aug 8 at 20:42
I don't know that this is the best answer, but i do like the script option because it means all i need to do is read a comment in the file and I can remember exactly how to use it in the future. So thank you, for that reason I have accepted your answer.
– Chris
Aug 8 at 17:42
I don't know that this is the best answer, but i do like the script option because it means all i need to do is read a comment in the file and I can remember exactly how to use it in the future. So thank you, for that reason I have accepted your answer.
– Chris
Aug 8 at 17:42
1
1
Hi @Chris, thanks, that's actually why I do lots of utility scripts, even if they are just a couple lines, it's common to have the same problems over and over again, and sometimes, even for just a one-liner, you end up spending some fair amount of time to get it right, I usually do those directly on the interactive shell and when they are working, I put on a file, parametrize them a bit and add a "Usage: " help. Months later this saves me many hours of re-work..
– Fabiano
Aug 8 at 20:41
Hi @Chris, thanks, that's actually why I do lots of utility scripts, even if they are just a couple lines, it's common to have the same problems over and over again, and sometimes, even for just a one-liner, you end up spending some fair amount of time to get it right, I usually do those directly on the interactive shell and when they are working, I put on a file, parametrize them a bit and add a "Usage: " help. Months later this saves me many hours of re-work..
– Fabiano
Aug 8 at 20:41
This one for example I also started as a one-liner, similar to @wurtel's (but four commands instead of three:
find, while, ln plus the additional mkdir), the rest is just some boiler plate to treat corner cases (like filenames with exotic chars such as n, handle both absolute and relative paths, verbosity, accept multiple parameters to the find, etc) and then it becomes pretty hard to read and understand a few days later..– Fabiano
Aug 8 at 20:42
This one for example I also started as a one-liner, similar to @wurtel's (but four commands instead of three:
find, while, ln plus the additional mkdir), the rest is just some boiler plate to treat corner cases (like filenames with exotic chars such as n, handle both absolute and relative paths, verbosity, accept multiple parameters to the find, etc) and then it becomes pretty hard to read and understand a few days later..– Fabiano
Aug 8 at 20:42
add a comment |
If you already have the necessary directories created in the target location, then with the GNU implementations of find and xargs, it's not too difficult:
find ~/path/to/src -name "*stringtomatch*" -printf "%P" |
xargs -r0 --replace ln -s ~/path/to/src/'' ~/path/to/dest/''
The -printf "%P" outputs the path with the source directory parameter removed, and ends with a null byte.
xargs then reads the find output.
-0 indicates the parameters to use are null-separated.
--replace tells xargs to replace with the argument (also implies running one command per argument).
Finally the command to replace arguments into is given.
the%Pis very neat!!
– Fabiano
Aug 8 at 20:44
add a comment |
If you already have the necessary directories created in the target location, then with the GNU implementations of find and xargs, it's not too difficult:
find ~/path/to/src -name "*stringtomatch*" -printf "%P" |
xargs -r0 --replace ln -s ~/path/to/src/'' ~/path/to/dest/''
The -printf "%P" outputs the path with the source directory parameter removed, and ends with a null byte.
xargs then reads the find output.
-0 indicates the parameters to use are null-separated.
--replace tells xargs to replace with the argument (also implies running one command per argument).
Finally the command to replace arguments into is given.
the%Pis very neat!!
– Fabiano
Aug 8 at 20:44
add a comment |
If you already have the necessary directories created in the target location, then with the GNU implementations of find and xargs, it's not too difficult:
find ~/path/to/src -name "*stringtomatch*" -printf "%P" |
xargs -r0 --replace ln -s ~/path/to/src/'' ~/path/to/dest/''
The -printf "%P" outputs the path with the source directory parameter removed, and ends with a null byte.
xargs then reads the find output.
-0 indicates the parameters to use are null-separated.
--replace tells xargs to replace with the argument (also implies running one command per argument).
Finally the command to replace arguments into is given.
If you already have the necessary directories created in the target location, then with the GNU implementations of find and xargs, it's not too difficult:
find ~/path/to/src -name "*stringtomatch*" -printf "%P" |
xargs -r0 --replace ln -s ~/path/to/src/'' ~/path/to/dest/''
The -printf "%P" outputs the path with the source directory parameter removed, and ends with a null byte.
xargs then reads the find output.
-0 indicates the parameters to use are null-separated.
--replace tells xargs to replace with the argument (also implies running one command per argument).
Finally the command to replace arguments into is given.
edited Aug 8 at 9:40
Stéphane Chazelas
330k58 gold badges642 silver badges1010 bronze badges
330k58 gold badges642 silver badges1010 bronze badges
answered Aug 8 at 9:20
wurtelwurtel
11.8k1 gold badge16 silver badges29 bronze badges
11.8k1 gold badge16 silver badges29 bronze badges
the%Pis very neat!!
– Fabiano
Aug 8 at 20:44
add a comment |
the%Pis very neat!!
– Fabiano
Aug 8 at 20:44
the
%P is very neat!!– Fabiano
Aug 8 at 20:44
the
%P is very neat!!– Fabiano
Aug 8 at 20:44
add a comment |
With zsh (assuming the target directories already exist):
autoload zmv # best in ~/.zshrc
zmv -Ls ~/path/to/src/'(**/)(*stringtomatch*)' ~/path/to/dst/'$1$2'
If your ln implementation is the GNU one, you can use its -r option to make relative symlinks (here also -v for verbose).
zmv -Ls -o-rv ~/path/to/src/'(**/)(*stringtomatch*)' ~/path/to/dst/'$1$2'
add a comment |
With zsh (assuming the target directories already exist):
autoload zmv # best in ~/.zshrc
zmv -Ls ~/path/to/src/'(**/)(*stringtomatch*)' ~/path/to/dst/'$1$2'
If your ln implementation is the GNU one, you can use its -r option to make relative symlinks (here also -v for verbose).
zmv -Ls -o-rv ~/path/to/src/'(**/)(*stringtomatch*)' ~/path/to/dst/'$1$2'
add a comment |
With zsh (assuming the target directories already exist):
autoload zmv # best in ~/.zshrc
zmv -Ls ~/path/to/src/'(**/)(*stringtomatch*)' ~/path/to/dst/'$1$2'
If your ln implementation is the GNU one, you can use its -r option to make relative symlinks (here also -v for verbose).
zmv -Ls -o-rv ~/path/to/src/'(**/)(*stringtomatch*)' ~/path/to/dst/'$1$2'
With zsh (assuming the target directories already exist):
autoload zmv # best in ~/.zshrc
zmv -Ls ~/path/to/src/'(**/)(*stringtomatch*)' ~/path/to/dst/'$1$2'
If your ln implementation is the GNU one, you can use its -r option to make relative symlinks (here also -v for verbose).
zmv -Ls -o-rv ~/path/to/src/'(**/)(*stringtomatch*)' ~/path/to/dst/'$1$2'
answered Aug 8 at 9:45
Stéphane ChazelasStéphane Chazelas
330k58 gold badges642 silver badges1010 bronze badges
330k58 gold badges642 silver badges1010 bronze badges
add a comment |
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f534489%2frecursively-find-file-names-containing-string-and-symlink-files-in-another-dir%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
I've deleted my answer, since I'm still working on to find how to preserve the path in the destination
– Inian
Aug 8 at 7:38