rechercher la commande, énumérer la sortie et autoriser la sélection?

10

Lorsque j'utilise find, il trouve souvent plusieurs résultats comme

find -name pom.xml
./projectA/pom.xml
./projectB/pom.xml
./projectC/pom.xml

Je souhaite souvent ne sélectionner qu'un résultat spécifique (par exemple edit ./projectB/pom.xml). Existe-t-il un moyen d'énumérer la findsortie et de sélectionner un fichier à passer dans une autre application? comme:

find <print line nums?> -name pom.xml
1 ./projectA/pom.xml
2 ./projectB/pom.xml
3 ./projectC/pom.xml

!! | <get 2nd entry> | xargs myEditor

?

[Modifier] J'ai rencontré quelques bugs particuliers avec certaines des solutions mentionnées. Je voudrais donc expliquer les étapes pour reproduire:

git clone http://git.eclipse.org/gitroot/platform/eclipse.platform.swt.git
cd eclipse.platform.swt.git
<now try looking for 'pom.xml' and 'feature.xml' files>

[Modifier] Solution 1 Jusqu'à présent, une combinaison de 'nl' (sortie énumérée), head & tail semble fonctionner si je les combine en fonctions et utilise $ (!!).

c'est à dire:

find -name pom.xml | nl   #look for files, enumirate output.

#I then define a function called "nls"
nls () {
  head -n $1 | tail -n 1
}

# I then type: (suppose I want to select item #2)
<my command> $(!!s 2)

# I press enter, it expands like: (suppose my command is vim)
vim $(find -name pom.xml |nls 2)

# bang, file #2 opens in vim and Bob's your uncle.

[Modifier] Solution 2 L' utilisation de "select" semble également très bien fonctionner. ex:

  findexec () {
          # Usage: findexec <cmd> <name/pattern>
          # ex: findexec vim pom.xml
          IFS=$'\n'; 
          select file in $(find -type f -name "$2"); do
                  #$EDITOR "$file"
                  "$1" "$file"
                  break
          done;  
          unset IFS
  }
Leo Ufimtsev
la source
Est l' Your find command | head -TheNumberYouWantaccomplissement de vos besoins? (Avec votre ligne: !! | head -2 | xargs myEditor)
ADDB
1
Consultez fzf , il lie ce type d'action à ^ T (par défaut)
Tavian Barnes

Réponses:

16

Utilisez bashla fonction intégrée select:

IFS=$'\n'; select file in $(find -type f -name pom.xml); do
  $EDITOR "$file"
  break
done; unset IFS

Pour la question "bonus" ajoutée dans le commentaire:

declare -a manifest
IFS=$'\n'; select file in $(find -type f -name pom.xml) __QUIT__; do
  if [[ "$file" == "__QUIT__" ]]; then
     break;
  else
     manifest+=("$file")
  fi
done; unset IFS
for file in ${manifest[@]}; do
    $EDITOR "$file"
done
# This for loop can, if $EDITOR == vim, be replaced with 
# $EDITOR -p "${manifest[@]}"
DopeGhoti
la source
4
+1 pour avoir proposé ce que je soupçonne être un verbe de commande très peu utilisé
roaima
J'y travaille. selectne semble pas convenir à la modification IFS.
DopeGhoti
3
Ah. ( IFS=$'\n'; select file in $(find -maxdepth 2 -name '*.txt'); do echo "$file"; done; )
roaima
J'aurais dû penser aux cordes de style C. Bien joué!
DopeGhoti
1
J'apprécierais quelques informations, @roaima: unix.stackexchange.com/questions/378282/…
DopeGhoti
3

Deux petites fonctions vous aideront à résoudre ce problème à condition que vos noms de fichiers ne contiennent pas de nouvelles lignes ou d'autres caractères non imprimables. (Il gère les noms de fichiers contenant des espaces.)

findnum() { find "$@" | sed 's!^\./!!' | nl; }
wantnum() { sed -nr "$1"'{s/^\s+'"$1"'\t//p;q}'; }

Exemple

findnum -name pom.xml
     1  projectA/pom.xml
     2  projectB/pom.xml
     3  projectC/pom.xml

!! | wantnum 2
projectB/pom.xml
roaima
la source
Handily, le nom de fichier explicite pom.xmlne contiendra jamais d'espaces (:
DopeGhoti
Il semble y avoir un bug dans ce qui précède. find -name pom.xml me donnera beaucoup de sortie, mais findnum ne me donne qu'une seule ligne. par exemple ./features/org.eclipse.swt.tools.feature/pom.xml ./examples/org.eclipse.swt.examples.ole.win32/pom.xml ./examples/org.eclipse.swt.examples/pom .xml ./examples/org.eclipse.swt.examples.views/pom.xml ./examples/org.eclipse.swt.examples.launcher/pom.xml ./examples/org.eclipse.swt.examples.browser. demos / pom.xml ./local-build/local-build-parent/pom.xml
Leo Ufimtsev
@Leo sur ce même jeu de données, comment avez-vous utilisé findnum?
roaima
Espérons que cette capture d'écran aide à expliquer le problème: i.imgur.com/hfneWJn.png Vous pouvez observer que feature.xml donne 3 résultats. avec la fonction findnum, j'obtiens une erreur. avec fundnum pom.xml, il n'imprime qu'un seul résultat alors que find -name pom.xml affiche 3 résultats. J'ai mis à jour ma question pour expliquer comment obtenir un ensemble de données. (c'est un simple dépôt git)
Leo Ufimtsev
1
@DopeGhoti, bien qu'il puisse se trouver dans un répertoire nommé avec un espace blanc d:
Wildcard
3

vous pouvez obtenir la tête des sorties totales et la queue avec -1. cela peut diriger la sortie dans n'importe quelle autre commande ou éditeur, par exemple.

(obtenez-moi 100 lignes et imprimez-moi à la dernière pipe les 100) trouver. | tête -100 | queue -1

xxx@prod01 (/home/xxx/.ssh) $ find .
.
./authorized_keys
./id_rsa
./id_rsa.pub
./id_rsa_b_x.pub
./id_rsa_a_y.pub
./known_hosts

xxx@prod01 (/home/xxx/.ssh) $ find . | head -3
.
./authorized_key
./id_rsa

xxx@prod01 (/home/xxx/.ssh) $ find . | head -3 | tail -1
./id_rsa    



eg: vim "$(find . | head -100 | tail -1)"

vous obtiendrez la 100e ligne de recherche.

igiannak
la source
1
Eh bien, la solution simple semble être la meilleure. Votre réponse combinée avec 'nl' et '$ (!!)' semble très bien fonctionner en fait. J'ai posté des détails dans ma question. Merci pour la réponse.
Leo Ufimtsev
1

Si votre objectif est de modifier des fichiers après une recherche, essayez sag / sack .

Exemple:

$ sag skb_copy                                                                
sack__option is: -ag

============> running ag! <============

===> Current Profile: no_profile
===> Using flags: 
===> Searching under: /home/fklassen/git/pvc-appliance/kernel/drivers/ixgbevf
===> Searching parameters: skb_copy


/home/fklassen/git/pvc-appliance/kernel/drivers/ixgbevf/kcompat.c
[1] 195:        skb_copy_bits(skb, offset, buffer, len) < 0)

/home/fklassen/git/pvc-appliance/kernel/drivers/ixgbevf/kcompat.h
[2] 1774:   if (skb_copy_bits(skb, offset, buffer, len) < 0)
[3] 2321:#define skb_copy_to_linear_data(skb, from, len) \
[4] 2323:#define skb_copy_to_linear_data_offset(skb, offset, from, len) \

... puis pour éditer le dernier résultat de recherche ....

F 4

L'avantage est que vous pouvez revenir en arrière plus tard modifier le premier résultat de recherche avec

F 1
Fredk
la source