encontrar comando, enumerar salida y permitir selección?

10

Cuando uso find, a menudo encuentra múltiples resultados como

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

A menudo quiero seleccionar solo un resultado específico, (por ejemplo edit ./projectB/pom.xml). ¿Hay alguna manera de enumerar la findsalida y seleccionar un archivo para pasar a otra aplicación? me gusta:

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

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

?

[Editar] Me he encontrado con algunos errores extraños con algunas de las soluciones mencionadas. Entonces me gustaría explicar los pasos para reproducir:

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>

[Editar] Solución 1 Hasta ahora, una combinación de 'nl' (salida de enumeración), head & tail parece funcionar si los combino en funciones y uso $ (!!).

es decir:

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.

[Editar] Solución 2 El uso de "select" parece funcionar bastante bien también. 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
fuente
¿ Your find command | head -TheNumberYouWantCumple sus requisitos? (Con su línea: !! | head -2 | xargs myEditor)
ADDB
1
Echa un vistazo a fzf , vincula este tipo de acción a ^ T (por defecto)
Tavian Barnes

Respuestas:

16

Use bashincorporado select:

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

Para la pregunta de "bonificación" agregada en el comentario:

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
fuente
44
+1 por ofrecer lo que sospecho es un verbo de comando muy poco usado
roaima
Estoy trabajando en eso. selectno parece ubicarse bien con alteraciones IFS.
DopeGhoti
3
Ah ( IFS=$'\n'; select file in $(find -maxdepth 2 -name '*.txt'); do echo "$file"; done; )
roaima
Debería haber pensado en cuerdas de estilo C. ¡Bien hecho!
DopeGhoti
1
Agradecería algunas ideas, @roaima: unix.stackexchange.com/questions/378282/…
DopeGhoti
3

Dos pequeñas funciones lo ayudarán a resolver esto siempre que sus nombres de archivo no contengan nuevas líneas u otros caracteres que no se impriman. (Maneja nombres de archivos que contienen espacios).

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

Ejemplo

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

!! | wantnum 2
projectB/pom.xml
roaima
fuente
Prácticamente, el nombre de archivo explícito pom.xmlnunca contendrá espacios en blanco (:
DopeGhoti
Parece que hay algún error en lo anterior. find -name pom.xml me dará mucha salida, pero findnum solo me da una sola línea. por ejemplo ./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 en ese mismo conjunto de datos, ¿cómo lo usó findnum?
roaima
Esperemos que esta captura de pantalla ayude a explicar el problema: i.imgur.com/hfneWJn.png Puede observar que feature.xml produce 3 resultados. con la función findnum me sale un error. con fundnum pom.xml solo imprime un resultado, mientras que find -name pom.xml imprime 3 resultados. Actualicé mi pregunta para explicar cómo obtener el conjunto de datos. (es un simple repositorio de git)
Leo Ufimtsev
1
@DopeGhoti, aunque podría estar en un directorio llamado con espacios en blanco d:
Comodín
3

podrías obtener la cabeza de las salidas totales y ajustarla con -1. esto puede canalizar la salida en cualquier otro comando o editor, por ejemplo.

(consígueme 100 líneas e imprímame en la última tubería las 100) encontrar. El | cabeza -100 | cola -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)"

te dará la línea número 100 de hallazgos.

igiannak
fuente
1
Bueno, la solución simple parece ser la mejor. Su respuesta combinada con 'nl' y '$ (!!)' parece funcionar bastante bien en realidad. Publiqué detalles en mi pregunta. Gracias por responder.
Leo Ufimtsev
1

Si su objetivo es editar archivos después de una búsqueda, intente sag / sack .

Ejemplo:

$ 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) \

... para editar el último resultado de búsqueda ...

F 4

La ventaja es que puede volver más tarde y editar el primer resultado de búsqueda con

F 1
fredk
fuente