Вопрос: Командная строка Linux / Перенос файлов, отфильтрованных по лексикографическому порядку


У меня есть несколько файлов в каталоге, которые называются IMG_0001.jpg ... IMG_9999.jpg, Я хочу переместить в другой каталог файлы, которые лексикографически имеют имя, большее, чем IMG_9431.jpg Как я могу это сделать?


4
2017-09-16 08:47


Источник




Ответы:


Вы можете использовать sort а также sed для получения списка файлов больше, чем некоторая строка:

$ ls -v
0?#Li  23?24  E.See  NULib  Yoush  ce-Su  edint  ethat  ibble  itwil  lines  of16   plesA  ryGen  t6?#C  witht  #ver
0?#mo  25?i   Examp  NYWAR  along  cribb  edist  ev     ibrar  ix B.  mapfo  ofthe  ppend  sdist  tetot  y8?#9  (atyo
0,22   27?#   FORAP  NextA  areFo  dacop  edwar  frees  ic11   lPubl  mored  oftwa  publi  sefor  theGN  yGene  )1995
1.scr  02111  Finla  Peter  aryis  datio  eful,  ftheG  ight(  landJ  mport  on23#  ralPu  se,or  tunde  yofth  ,USA.
1-200  ARTIC  GIMPT  RANTY  avere  difyi  eitan  ftwar  imbal  lbeus  ncerK  on,MA  raryG  shedb  t,wri  ytheF  ;ifno
2John  Appen  HANTA  Softw  bleof  dix B  enera  ght(C  impli  ld7?#  nc.,5  oolki  raryi  simpl  ublic  #19?#  ;with
4?#Th  BILIT  HOUTA  TNESS  blic2  e.py4  enthe  gtk26  ingar  lePla  ngpix  opyri  rdraw  sion.  ucanr  #Bost   Code
5?#GT  Backi  K-The  U17?#  brary  e.pyB  eralP  he21   ion)a  lesPr  nseas  oshMa  reeSo  sion2  undat  #Free
9Temp  Conte  Libra  ULARP  cDona  eExam  ermso  hehop  ion,I  lesTa  ntsB.  ouldh  re;yo  slibr  uropt  #Lice
13?#1  Copyr  Licen  URPOS  ceive  eFoun  erver  her12  islib  lescr  nylat  outev  ribut  s,Spe  utWIT  #MERC
15?#b  C)200  Matti  YorFI  cense  eGNUL  etail  hisli  ite33  lesim  n;eit  ple.p  rthet  s.18   vpyth  #Thi

$ mkdir greater-than-sion

Вот волшебство:

$ find -type f -print0 | 
  sort -z |
  sed -z '1,/sion/d' | 
  xargs -0 mv -t greater-than-sion

линии:

  1. распечатать список файлов, разделенных NUL вместо новых строк (-print0)
  2. сортировать их
  3. удалить строки ниже чем (включительно) некоторой строки (здесь sion) - обратите внимание, что это работает только с GNU sed, который реализует -z вариант для синтаксического анализа NUL-термированный ввод
  4. передать этот список mv с xargs

И желаемый результат:

$ ls -R
.:
 Code  ;ifno  25?i   avere  Conte  edist  erver  GIMPT               ic11   K-The  lines  nseas  opyri  raryG  se,or
#19?#  ;with  27?#   Backi  Copyr  edwar  etail  greater-than-sion/  ight(  landJ  lPubl  ntsB.  oshMa  raryi  sefor
#Bost  0?#Li  2John  BILIT  cribb  eExam  ethat  gtk26               imbal  lbeus  mapfo  NULib  ouldh  rdraw  shedb
#Free  0?#mo  4?#Th  bleof  dacop  eFoun  ev     HANTA               impli  ld7?#  Matti  nylat  outev  re;yo  simpl
#Lice  0,22   5?#GT  blic2  datio  eful,  Examp  he21                ingar  lePla  mored  NYWAR  Peter  reeSo  sion.
#MERC  02111  9Temp  brary  difyi  eGNUL  Finla  hehop               ion)a  lescr  mport  of16   ple.p  ribut
#Thi   1.scr  along  C)200  dix B  eitan  FORAP  her12               ion,I  lesim  n;eit  ofthe  plesA  rthet
#ver   1-200  Appen  cDona  e.py4  enera  frees  hisli               islib  lesPr  nc.,5  oftwa  ppend  ryGen
(atyo  13?#1  areFo  ceive  e.pyB  enthe  ftheG  HOUTA               ite33  lesTa  ncerK  on,MA  publi  s,Spe
)1995  15?#b  ARTIC  cense  E.See  eralP  ftwar  ibble               itwil  Libra  NextA  on23#  ralPu  s.18
,USA.  23?24  aryis  ce-Su  edint  ermso  ght(C  ibrar               ix B.  Licen  ngpix  oolki  RANTY  sdist

./greater-than-sion:
sion2  Softw  t6?#C  theGN  tunde  ublic  ULARP  uropt  utWIT  witht  yGene  YorFI  ytheF
slibr  t,wri  tetot  TNESS  U17?#  ucanr  undat  URPOS  vpyth  y8?#9  yofth  Yoush

4
2017-09-16 10:52



Хороший. Я полностью забыл о sed Вот. - slhck
Что делает «sed -z»? Быстрая проверка и не удалось найти объяснение для опции -z. - jaychris
Обрабатывает строки, разделенные нулевым символом, вместо символа новой строки. Об этом говорится в руководстве. - Ярослав Рахматуллин
Обратите внимание, что это опция только для GNU, поэтому не BSD sed, (cc @jaychris) - slhck
Спасибо Ярослав & slhck. Я попробовал руководство и googled, но не получил этот вариант. Похоже, что sed, к которому я обращался, не является версией GNU. - jaychris


С расширение скобы, который доступен в Bash 3 и выше, а также Zsh и несколько других оболочек: *

mv IMG_{9431..9999}.jpg some_other_dir

Скобки будут расширены до всех чисел между 9431 и 9999, поэтому это эквивалентно написанию:

mv IMG_9431.jpg IMG_9432.jpg … IMG_9999.jpg some_other_dir

Это не удастся, если слишком много файлов (см. это сообщение о ARG_MAX для получения дополнительной информации.)

Если в вашей оболочке отсутствуют функции расширения фигурных скобок или у вас слишком много файлов, вы можете сделать это - что может быть немного медленнее:

for n in $(seq 9431 9999); do mv "IMG_$n.jpg" some_other_dir; done

Если вы действительно хотите сортировать лексикографически, взгляните на Ответ Ярослав Рахматуллин, Намного лучше, чем здесь.

Вам нужно будет как-то отсортировать имена файлов. Это то, что я придумал очень быстро, и это не очень и далеко не идеально. Он работает с GNU / Linux (grep, sort, xargs) и имеет дело с любыми именами файлов, включая кавычки и пробелы.

tmp="$(mktemp /tmp/files.XXX)"
find . -type f -name 'IMG*'  -maxdepth 1 -print0 | sort -z > "$tmp"
line=$(grep -nz IMG_9984.jpg "$tmp" | cut -d: -f1)
tr '\0\n' '\n\0' < "$tmp" | tail -n "+$line" | tr '\0\n' '\n\0' |
xargs -0 -I{} echo mv {} some_other_dir
rm "$tmp"

Удалить echo когда вы уверены, что это делает то, что вы хотите. Что мы здесь делаем:

  • Создайте временный файл для хранения имен файлов.

  • Найдите все файлы, соответствующие шаблону, и отсортируйте их во временный файл. Записи разделены NUL персонажи (-print0, -z), поэтому мы можем иметь дело с любым именем файла.

  • Найдите номер строки в имени файла, например. IMG_9984.jpg

  • Замена NUL и новая строка во временном файле так tail может справиться с этим,

  • Поменяйте их так, чтобы xargs может справиться с ним (-0) а также mv файлы в другой каталог.

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


6
2017-09-16 09:03



Возможно, обратите внимание, что это Bash специфический (?). Более экзотическая нота заключается в том, что она потерпит неудачу, если в итоге будет больше аргументов ARG_MAX. Тем не менее, на пару порядков избавиться от этого случая. - Daniel Andersson
@DanielAndersson Я собирался добавить решение для старых / альтернативных оболочек. Это в Bash 3 и выше, также в Zsh и ksh, возможно, другие. - slhck
Как раз для знания, как бы я это сделал, если в файлах не было шаблона, и я просто хотел получить все файлы «лексикографически больше, чем» определенное имя файла? - Paralife
@Paralife Может показаться сложным - см. Мой обновленный ответ. Но решение Ярослава определенно более прямолинейно. - slhck
хорошо, что здесь? Дайте принятый ответ на более общее решение Ярослава, которое может быть полезно и для других ситуаций, или оставить этот принятый ответ, поскольку он решает тонкий конкретный вопрос, который я задал, и проще? - Paralife