Question Ligne de commande Linux / Déplacer les fichiers filtrés par ordre lexicographique


J'ai des fichiers dans un répertoire qui sont nommés IMG_0001.jpg ... IMG_9999.jpg. Je veux déplacer dans un autre répertoire les fichiers ayant le nom lexicographiquement supérieur à IMG_9431.jpg Comment puis je faire ça?


4
2017-09-16 08:47


origine




Réponses:


Vous pouvez utiliser sort et sed pour obtenir une liste de fichiers plus grande que certaines chaînes:

$ 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

Voici la magie:

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

Lignes:

  1. imprimer une liste de fichiers, séparés par NUL au lieu de nouvelles lignes (-print0)
  2. les trier
  3. supprimer des lignes plus bas que (inclus) de la ficelle (ici sion) - notez que cela ne fonctionne qu'avec GNU sed, qui implémente un -z option pour analyser NULentrée terminée
  4. passer cette liste à mv avec xargs

Et le résultat souhaité:

$ 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



Joli. J'ai totalement oublié sed ici. - slhck
Que fait 'sed -z'? A effectué une vérification rapide et n'a pas trouvé l'explication de l'option -z. - jaychris
Traite les lignes séparées par le caractère nul au lieu du caractère de nouvelle ligne. Ceci est indiqué dans le manuel. - Ярослав Рахматуллин
Notez que c'est une option uniquement GNU, donc pas BSD sed. (cc @jaychris) - slhck
Merci Ярослав & slhck. J'ai essayé le manuel et googlé mais n'a pas obtenu cette option. On dirait que le sed auquel j'ai accédé n'est pas la version GNU. - jaychris


Avec extension d'accolade, disponible dans Bash 3 et supérieur, ainsi que Zsh et plusieurs autres shells: *

mv IMG_{9431..9999}.jpg some_other_dir

Les accolades seront étendues à tous les nombres entre 9431 et 9999, ce qui revient à écrire ceci:

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

Cela échouera s'il y a trop de fichiers (voir ce post sur ARG_MAX pour les informations de fond.)

Si votre shell ne dispose pas de fonctions d’accessoires, ou si vous avez trop de fichiers, vous pouvez le faire - ce qui pourrait être un peu plus lent:

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

Si vous voulez vraiment trier lexicographiquement, regardez La réponse de Ярослав Рахматуллин. Beaucoup plus agréable que ce qui suit

Vous devrez trier vos noms de fichiers d'une manière ou d'une autre. C’est ce que j’ai trouvé très vite, et ce n’est pas beau et loin d’être idéal. Cela fonctionne avec GNU / Linux (grep, sort, xargs) et gère tous les noms de fichiers, y compris les guillemets et les espaces.

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"

Retirer le echo quand vous êtes sûr que cela fait ce que vous voulez. Ce que nous faisons ici:

  • Créez un fichier temporaire pour contenir les noms de fichiers.

  • Recherchez tous les fichiers correspondant au modèle et triez-les dans un fichier temporaire. Les enregistrements sont délimités par NUL personnages (-print0, -z) nous pouvons donc traiter n'importe quel nom de fichier.

  • Recherchez le numéro de ligne du nom du fichier, par ex. IMG_9984.jpg

  • Échanger NUL et newline dans le fichier temporaire alors tail peut y faire face.

  • Les échanger pour xargs peut y faire face (-0) et mv les fichiers dans l'autre répertoire.

Ce serait plus facile si nous n'avions pas à gérer des fichiers contenant des guillemets ou des espaces, mais ... c'est juste moi. Mieux vaut prévenir que guérir.


6
2017-09-16 09:03



Notez peut-être que c'est spécifique à Bash (?). Une note plus exotique est qu’elle échouera si l’on étend à plus d’arguments ARG_MAX au total. Quelques ordres de grandeur à épargner dans ce cas, cependant. - Daniel Andersson
@DanielAndersson J'allais ajouter une solution pour les shells plus anciens / alternatifs. C'est dans Bash 3 et au-dessus, également dans Zsh et ksh, peut-être d'autres. - slhck
Juste pour la connaissance, comment pourrais-je le faire s'il n'y avait pas un modèle dans les fichiers et je voulais juste obtenir tous les fichiers "lexicographiquement plus grands que" un nom de fichier spécifique? - Paralife
@Paralife Pourrait être difficile - voir ma réponse mise à jour. Mais la solution de оросла est certainement plus simple. - slhck
ok ce qui est juste ici? Donnez une réponse acceptée à la solution plus générique de оросла qui pourrait être utile à d'autres situations également, ou laissez cette réponse acceptée car elle résout bien la question spécifique que j'ai posée et est plus simple? - Paralife