Filtrar columnas basándose en el valor de otra columna

Tengo un file de text con dos columnas y más de 3,000,000 filas. El formatting es el siguiente

Filename1.txt Num1 Filename2.txt Num2 Filename3.txt Num3 

Quiero copyr todos los nombres de file para los cuales Numx correspondiente es mayor que 50 y less de 200 en un file diferente.

Una vez que copie esos nombres de file en un file diferente, quiero copyr todos esos files en una carpeta diferente.

¿Cómo puedo hacer eso?

Si lo desea, puede hacer la comparación y copy al mismo time con awk :

 awk '$2>50 && $2<200 {system("cp -- "$1" /path/to/destination/")}' file.txt 

Suponiendo que desea copyr los files al directory de destination , cámbielos para satisfacer sus necesidades.

  • $2>50 && $2<200 hace la comparación requerida

  • si coincide, entonces se ejecuta la operación cp ( {system("cp -- "$1" /path/to/destination/")} ), hecho por la function system() de awk

Consideremos este file de testing:

 $ cat file Filename1.txt 49 Filename2.txt 72 Filename3.txt 189 Filename4.txt 203 

Para seleccionar solo aquellos files para los cuales la segunda columna es mayor o igual a 50 y también menor o igual a 200:

 $ awk '$2>=50 && $2<=200 { print $1}' file Filename2.txt Filename3.txt 

Para poner esos nombres de file en un nuevo file en alguna ruta:

 awk '$2>=50 && $2<=200 { print $1}' file >/path/to/newfile 

Copiando los files seleccionados

Suponiendo que los numbers son integers, intente:

 while read fname num; do [ "$num" -ge 50 ] && [ "$num" -le 200 ] && cp -- "$fname" /some/path/ ; done <file 

O, para aquellos que prefieren su código distribuido en múltiples líneas:

 while read fname num do [ "$num" -ge 50 ] && [ "$num" -le 200 ] && cp -- "$fname" /some/path/ done <file 

La pregunta está labelda sed y grep , por lo que asumo que hay interés en una respuesta que usa expresiones regulares. Además, la pregunta indica que el file de datos de input es grande, por lo que asumo que el performance es una consideración.

También supongo que, dado que el file de input contiene un nombre de file por línea, no habrá nombres de file (patológicos) que contengan caracteres de nueva línea.

Las otras respuestas generan efectivamente un process de cp para cada file. Esto causa una networkingucción de performance innecesaria. En su lugar, podemos usar las instalaciones de xargs para llamar a cp con tantos nombres de files como pueda caber en una línea de command.

 sed -rn 's/ (5[1-9]|[6-9].|1..)$//p' input.txt | tr '\n' '\0' | xargs -0 cp -t /destdir 

The sed usa una expresión regular para coincidir con el intervalo numérico cerrado (50, 200) . El uso de expresiones regulares para las desigualdades numéricas no siempre es lo más elegante que se puede hacer, pero en este caso la expresión requerida es bastante directa.

Estamos asumiendo que los nombres de file no contienen líneas nuevas, pero pueden contener otros caracteres inútiles, como espacios. xargs manejará esto correctamente si se le dan datos \0 -importados, entonces usamos tr para convertir todas las líneas nuevas a caracteres nulos.

Lo anterior asume las versiones GNU de sed y xargs . Si en cambio tiene versiones BSD (por ejemplo, OSX), entonces el command es ligeramente diferente:

 sed -En 's/ (5[1-9]|[6-9].|1..)$//p' input.txt | tr '\n' '\0' | xargs -0 -J {} cp {} /destdir 

Estos commands generarán exactamente una copy de sed , tr y xargs . Habrá más de un spawn de cp , pero cada uno copyrá varios files: xargs intentará llenar cada línea de command cp para lograr una utilización eficiente. Esto debería proporcionar una mejora significativa del performance sobre las otras respuestas cuando los datos de input son grandes.