1

I'm trying to create multiple symbolic links using wildcard, here the example:

$ ls -R
.:
TXT  a  b

./TXT:

./a:
a.txt

./b:
b.txt

There is a "parent directoory" containing various subdirs: a, b, TXT. In "a" and "b" there are various text files (a.txt, b.txt in the above example).

I want to create "relative" symbolic links to each ".txt" files whitin the "TXT" subdir. But:

  • without using "find"
  • without "cd" in TXT directory

In other words I want to know why a command like the following doesn't work:

ln -s ../*/*txt TXT/

With a previus "cd TXT" it works:

cd TXT
ln -s ../*/*txt .

I think the issue appears due to bash expansion of "*" and "../", bash is not able to expand "../*/*.txt" because those files actually don't exist, so "ln" cannot create the desired links: it creates links to txt files of "one level up" dirs relative to the current workdir. It "cd" to ".." and considers all dirs at this level, looking for the ".txt" files within these.

Maybe "the rule" could be symlink TARGET has to:

  • point at the same time at real existing files (otherwise bash can't expand ".." or "*" in the right way)
  • and it has to be relative to the DIRECTORY that will contain the link

Could you confirm and explain what exactly is the problem and possible solutions?

PS. Using "find", a command like the following seems to work:

find ./ -path ./TXT -prune -o -iname "*.txt" -type f -exec ln -s ."{}" -t TXT/ \;

Note that even in this case I have to use a "non existing" path:

."{}"

But the -exec command just expands "{}" which is "./a/a.txt" and "./b/b.txt", so "ln" can build the right path relative to TXT destdir thanks to the prefixed dot ".".

  • Possible duplicate of Create symbolic links with wildcards – Romeo Ninov Dec 14 '17 at 10:19
  • @RomeoNinov not a duplicate. Your suggested question uses absolute symlinks. The question here is about the relative symbolic links not working – roaima Dec 14 '17 at 12:25
  • @roaima, the wildcard mechanism in shell is the same, independently of the type of symlink – Romeo Ninov Dec 14 '17 at 12:28
  • @RomeoNinov I don't see any answer there that is applicable to the problem described here – roaima Dec 14 '17 at 12:32
2

You're using this command

ln -s ../*/*txt TXT/

If you are in the directory containing a, b, and TXT then the shell will fail to expand ../*/*txt to match anything in a or b. You would have to use */*txt for that, but then the symbolic links inside TXT would be off by one level and they would need another ../ in their relative paths.

The easiest solution would be this, but you say you want to avoid cd

( cd TXT && ln -s ../*/*txt . )

Another solution would require fixing up the links in turn

for f in */*txt
do
    ln -s ../"$f" TXT
done

Be aware that because you have your source directories a and b at the same level as TXT, the wildcards in both of the suggestions will match all three directories.

  • for f in [a-z]*/*txt should solve in my case: I can name the files subdir (a, b in the example) as I prefer: I can choose names beginning in lowercase letter [a-z] and target dir TXT in caps. – Joe Dec 14 '17 at 13:22
  • The problem could poup up if a source subdir doesn't contain any *.txt file. In that case will be created an unwanted broken link in TXT named *.txt. This problem occurs also with the cd solution... That is the usual behavior of ln command, anyway should be better to create the link just in case the linked file really exists... – Joe Dec 14 '17 at 13:23
  • 1
    @Joe be very careful with your locale if you're expecting [a-z] to miss your uppercase TXT directory. Check with echo [a-z]*. – roaima Dec 14 '17 at 16:30
  • @Joe ln -s will create a symbolic link to anything, whether or not it exists. This isn't really "unusual behaviour", but you might prefer in this instance that ln -s didn't do that. – roaima Dec 14 '17 at 16:33
  • Yes indeed I'm using my above reported version based on "find". find command automatically filters just the existing files. Moreover it allow to refine the selection of the files which to create the links to (based on certain pattern in their name for example). And it allow subdir exclusion too, by the "-path $DIRTOEXCLUDE -prune". Anyway I asked just to understand the wildcard behavior along the symlink command ln. A remark: with hardlink there isn't any problem... but hard link and symlink are not the same... Thank you for suggests! :) – Joe Dec 14 '17 at 17:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.