Est-il possible de remplacer la commande «cd» intégrée à la ligne de commande?

22

À peu près à chaque fois que je «cd» vers un répertoire différent sur ma machine (dans ce cas, exécutant Mac OS X 10.6.7) via la ligne de commande (qui est bash), je tape immédiatement «ls» pour obtenir la liste des contenus dans ce répertoire. J'essaie de trouver un moyen de remplacer 'cd' afin qu'il change dans le répertoire demandé et me donne ensuite la liste en une seule fois.

J'ai pu obtenir les fonctionnalités de base que je cherche à travailler avec la ligne suivante ajoutée à mon ~ / .bash_profile

function cl() { cd "$@"; ls -l; }

Cela fonctionne comme prévu. Passer au répertoire demandé puis me montrer le contenu. Là où je rencontre un problème, j'essaie de remplacer "cd" lui-même au lieu de créer une nouvelle commande "cl".

Les choses suivantes ne fonctionnent pas

##### Attempt 1 #####
# Hangs the command line

function cd() { cd "$@"; ls -l; }


##### Attempt 2 #####
# Hangs the command line

function cd() { 'cd' "$@"; ls -l; }


##### Attempt 3 #####
# Does not change directory. 
# Does list contents, but of the directory where you started.

function cd() { /usr/bin/cd "$@"; ls -l; }


#### Other attempts that fail in various ways #####
alias cd=cd "$@"; ls -la;
alias cd="cd '$@'; ls -la;"
alias cd='cd "$@"'; ls -la;
alias cd=/usr/bin/cd "$@"; ls -la;

J'ai également essayé plusieurs autres itérations qui ne sont pas répertoriées ainsi que la création d'un alias qui pointe vers la fonction «cl» de travail. Rien de tout cela n'a fonctionné.

Ce que j'ai lu dans la documentation parle du fait que 'cd' ne peut pas être exécuté comme une commande externe (c'est ce que je comprends être la façon dont la fonction devrait l'utiliser).

Donc, je peux actuellement utiliser ma commande "cl" et obtenir ce que je veux, mais la question est / reste:

Existe-t-il un moyen de remplacer le comportement de 'cd' pour qu'il change dans le répertoire demandé et fasse ensuite autre chose?

Alan W. Smith
la source

Réponses:

30

Les éléments suivants devraient fonctionner:

function cd() { builtin cd "$@" && ls -l; }

Puisque la fonction est sur une seule ligne, assurez-vous qu'elle se termine avec ;comme ci-dessus afin de fonctionner correctement.

Gaffe
la source
Ne fonctionne pas pour un appel sans paramètre.
Daniel Beck
3
@DanielBeck - au moins sur mon Mac OSX (10.6.7), cela fonctionne bien avec un appel sans paramètre. Le comportement est qu'il change dans le répertoire personnel et fait ensuite la liste de ce répertoire. Duplication efficace de la fonctionnalité de l'ancien 'cd' avec la nouvelle fonctionnalité ajoutée à la fin.
Alan W. Smith
2
@Alan True, je l'ai testé en écrivant ce code ad-hoc dans le shell. Il semble que le comportement de cd ""(à quoi cette réponse devrait évaluer est différent de cd "$@"vide $@. Désolé de la confusion.
Daniel Beck
@DanielBeck - pas de soucis.
Alan W. Smith
2
Remarque: je change cela en réponse acceptée car c'est une réponse précise à la question. Celui de @RichHomolka est idéal pour adresser le principal, mais celui-ci est exactement ce qui peut être mis dans votre fichier ~ / .bash_profile.
Alan W. Smith
10

Je pense que vous courez dans une boucle. Votre cdfonction appelle cd, ce qui est ... la fonction.

Vous devez savoir builtinquel est un mot-clé qui permet à la recherche de commandes d'utiliser les commandes internes de Bash comme cd et non votre fonction

function cd
{
    builtin cd "$1"
    : do something else
}

De plus, l'appel /usr/bin/cdne fonctionnera jamais, même si une telle commande existait.

Ce qui se passerait:

  • Mon shell Bash est en dir /bash/dir.
  • J'exécute une commande /usr/bin/cd /dir/for/cd.
  • /usr/bin/cdva au dir /dir/for/cd.
  • /usr/bin/cd sort.
  • Bash est toujours actif /bash/dir, car le processus enfant ne /usr/bin/cdpeut pas affecter le parent.

Les alias sont également de simples substitutions de texte. Ils ne peuvent jamais avoir de paramètres.

Rich Homolka
la source
Je suggère builtin cd $@ && ls; car l' cdappel doit réussir pour que tout le reste ait du sens. N'oubliez pas non plus les cas particuliers tels que cd(aucun argument).
Daniel Beck
Note latérale: J'ai essayé de marquer cela comme la réponse acceptée, mais cela me dit que je dois attendre encore 6 minutes avant de pouvoir le faire. Je ne savais pas qu'il y avait un retard intégré avant que vous puissiez le faire.
Alan W. Smith
@Alan Une autre meilleure solution pourrait arriver dans un délai très raisonnable (c'est-à-dire ces quelques minutes que vous devez attendre). Je suppose que c'est pourquoi il y a un délai imposé par le système: vous devriez préférer la qualité à la vitesse. Cela ne devrait pas être trop gênant.
Daniel Beck
Et nous avons un gagnant. Cela fonctionne comme un champion. Par @DanielBeck, j'ai changé pour utiliser && et je l'ai condensé en une seule ligne avec: function cd {builtin cd "$ @" && ls -l; }
Alan W. Smith
@DanielBeck - Ouais, je ne m'en inquiéterai pas. Je ne l'avais jamais remarqué auparavant. Je peux y voir la logique, ça m'a un peu surpris.
Alan W. Smith
6

Je suggère de ne pas remplacer le cd car il existe d'autres scripts détournant la fonction «cd», par exemple, rvm. Il serait préférable de choisir un autre nom, comme «d», à la place et de ne pas spécifier le type «intégré» dans votre fonction; sinon, le pirate de l'air ne fonctionnerait pas. J'utilise le code ci-dessous:

function d() { cd "$@" && ls;} 
Loupe
la source
Je pensais que cela ne fonctionnerait pas, selon la question du PO.
user305964