Comment créer des liens symboliques vers tous les fichiers (classe de fichiers) d'un répertoire?

43

Je voudrais créer des liens symboliques ( ln -s) vers tous les fichiers (ou une classe de fichiers, par exemple se terminant par .bar) dans un certain répertoire. Dis que je suis dans le cwd et le type ls ../source/*.barme donne

foo.bar
baz.bar

comment puis-je passer la liste des paramètres pour ln -squ'il résout finalement

ln -s ../source/foo.bar
ln -s ../source/baz.bar

Bien sûr, je sais que je peux écrire un script bash, mais il devrait y avoir quelque chose de plus simple à impliquer xargs, car cela semble être une tâche courante - du moins pour moi.

dastrobu
la source

Réponses:

75

ln prend plusieurs arguments, mais n'oubliez pas de donner un répertoire cible dans ce cas.

Donc, dans votre exemple .est le répertoire cible, il devrait donc être aussi simple que

ln -s ../source/*.bar .

De man ln; la commande ci-dessus utilise le 3ème formulaire:

ln [OPTION]... [-T] TARGET LINK_NAME   (1st form)
ln [OPTION]... TARGET                  (2nd form)
ln [OPTION]... TARGET... DIRECTORY     (3rd form)
ln [OPTION]... -t DIRECTORY TARGET...  (4th form)
  • Dans le 1er formulaire, créez un lien vers TARGET avec le nom LINK_NAME.
  • Dans le 2ème formulaire, créez un lien vers TARGET dans le répertoire courant.
  • Dans les 3e et 4e formes, créez des liens vers chaque CIBLE dans RÉPERTOIRE.
mpy
la source
5
Vous venez de me sauver 5 solides minutes de ma vie, valant assez pour passer l'un d'entre eux en laissant un commentaire. :-)
moodboom
Cela ne fonctionne pas s'il n'y a pas de fichiers *.bar. Cela créera un lien avec le nom "*.bar", ce qui n'est pas ce que vous voulez.
Nimrod
1
@Nimrod: C'est vrai, mais vous pouvez dire à bash que vous voulez qu'il signale une erreur à la place via shopt -s failglob; voir par exemple unix.stackexchange.com/a/216227/33390 (l'équivalent dans zsh est setopt nomatch, qui est activé par défaut)
mpy
: applaudissements: sympa!
Chris Schmitz
3

Utilisation find

certainDir="/path/to/dir"
find -name "*.bar" -exec ln -s {} "$certainDir" \;

N'oubliez pas non plus d'utiliser des chemins d'accès complets (si possible) avec des liens symboliques.

juste
la source
2
Merci, mais n'est-ce pas find $certainDir -name "*.bar" -exec ln -s {} \;? Et pourquoi devrais-je utiliser des chemins d'accès complets? Je trouve assez pratique de savoir que les liens restent intacts lorsque je déplace une arborescence de répertoires autour de laquelle ont des liens internes.
dastrobu
Cela dépend de l'endroit où vous souhaitez créer un lien symbolique entre les répertoires. Et je ne me souviens pas pourquoi les chemins complets sont une bonne idée, cela aurait pu être pour des liens durs, mais j'ai brûlé cela dans mon esprit pour une raison. Hmmm.
justbrowsing
Merci, votre réponse est excellente. Étant donné que la réponse de mpy est la solution la plus simple à la question, le point lui revient. J'accepterais les deux réponses, si je le pouvais.
dastrobu
3

Vous pouvez essayer récursivement soit en utilisant globstar (bash / zsh défini par:) shopt -s globstar:

ls -vs ../**/*.bar .

Remarque: ajouté -vpour verbeux.

Ou si la liste est trop longue, utilisez l' findutilitaire:

find .. -name \*.bar -exec ln -vs "{}" dest/ ';'

Cela créera des liens dest/ou le changera .pour le dossier actuel.

kenorb
la source
La seconde est la bonne réponse.
Nimrod
0

cpavec -soption peut créer un lien logiciel (ou -lpour un lien matériel).

Du répertoire courant peut être utilisé comme ceci:

$ cp -s ../path/with/scripts/* .

Dans votre cas, ce sera comme ceci:

$ cp -s ../source/*.bar .
cy8g3n
la source