Копирование определенных файлов путем неравнодушного соответствия их именам к списку в текстовом файле

У меня есть каталог с файлами с названиями строк, которые все начинают с 5 числами (т.е. 12345_a_b, 23456_s_a), и у меня есть текстовый файл в рамках того же каталога, который имеет список имен файлов, названных таким же образом, однако только соответствие чисел и ничто после подчеркивания (т.е. 12345_q_p, 23456_p_l). Я хочу скопировать файлы в текущем каталоге в новый, но только они, где первые 5 чисел от имени файла соответствуют первым 5 числам каждого имени файла в текстовом файле, игнорируя все, что прибывает после. Кажется, что я могу использовать xargs, но я не уверен, как соответствовать именам частично. Кто-либо может помочь?

3
задан 26 January 2017 в 13:14

3 ответа

Выполните итерации по строкам с _ как эти IFS, получите желаемую первую часть, содержащую цифры и копию файлы, запускающиеся с тех цифр:

shopt -s nullglob
while IFS=_ read -r i _; do [[ $i =~ ^[0-9]{5}$ ]] && echo cp -it dest/ "${i}"*; done <file.txt

Расширенный:

#!/bin/bash
shopt -s nullglob  ##Expands to null string if no match while doing glob expansion,
                   ##rather than the literal
while IFS=_ read -r i _; do  ##Iterate over the lines of file.txt, 
                              ##with `_` as the `IFS` i.e. word splitting 
                              ##happens on each `_` only, variable `i` 
                              ##will contain the digits at start; `_` is a
                              ##throwaway variable containing the rest
    [[ $i =~ ^[0-9]{5}$ ]] \ ##Check if the variable contains only 5 digits
      && echo cp -it /destination/ "${i}"*  ##if so, copy the relevant files starting with those digits
done <file.txt

Замена file.txt с фактическим исходным файлом, и /destination/ с Вашим фактическим целевым каталогом. Здесь echo включен, чтобы сделать пробный прогон; если удовлетворенный командами, которые будут выполнены, просто избавьтесь от echo:

shopt -s nullglob
while IFS=_ read -r i _; do [[ $i =~ ^[0-9]{5}$ ]] && cp -it dest/ "${i}"*; done <file.txt
4
ответ дан 1 December 2019 в 13:23

Следующие команды должны добиться цели, можно обмениваться первыми несколькими переменными присвоениями с их литеральными значениями в цикле с условием продолжения вместо этого, если Вы предпочитаете.

#!/bin/bash
source_dir=/directory/containing/files
target_dir=/new/directory
list=/full/path/to/number_list
reg='^[0-9]{5} 
  • Эти read команда считает Ваш файл линию за линией, устанавливая содержание каждой строки в переменную 'строку'.
  • cp использование команды -t для поставления цели для копирования файлов в, и шаблон шарика "$source_dir"/"$line"* найдет любые файлы в исходном каталоге, которые запускаются с численного значения в переменной строки.
  • while цикл означает, что read и cp команды выполняются для каждой строки файла списка. IFS= средства, что, если существуют пробелы в Вашем файле списка, они будут включены в th строку поиска, это не непосредственно необходимо в этом примере, но полезно обычно, когда Вы хотите считать файл линию за линией.
while IFS= read -r line; do line=${line:0:5} [[ "$line" =~ $reg ]] && cp -t "$target_dir" "$source_dir"/"$line"* 2>/dev/null done < "$list"
  • Эти read команда считает Ваш файл линию за линией, устанавливая содержание каждой строки в переменную 'строку'.
  • cp использование команды -t для поставления цели для копирования файлов в, и шаблон шарика "$source_dir"/"$line"* найдет любые файлы в исходном каталоге, которые запускаются с численного значения в переменной строки.
  • while цикл означает, что read и cp команды выполняются для каждой строки файла списка. IFS= средства, что, если существуют пробелы в Вашем файле списка, они будут включены в th строку поиска, это не непосредственно необходимо в этом примере, но полезно обычно, когда Вы хотите считать файл линию за линией.
2
ответ дан 1 December 2019 в 13:23

Выполните цикл на своих файлах. В цикле узнают, соответствуют ли имена файлов именам файлов в Вашем текстовом файле с помощью grep.

Используя-q позволяют Вам использовать && cp, если он находит что-то.

#!/bin/bash
while IFS= read -r file; do
  grep -Eq "^${f:0:5}" your_text_file && cp ${file} /path/to/destination/
done <( (find . -type f -regex "^[0-9]{5}.*")

Это будет иметь немного служебными, когда у Вас будет огромное количество файлов. Но может использоваться для более сложных задач также...

1
ответ дан 1 December 2019 в 13:23

Другие вопросы по тегам:

Похожие вопросы: