texto - ¿Cómo mover y renombrar los documentos colocados en varias carpetas anidadas en una nueva carpeta única con python?
python crear carpeta si no existe (2)
¿Cómo funciona esto para ti?
import os
import pathlib
OLD_DIR = ''files''
NEW_DIR = ''new_dir''
p = pathlib.Path(OLD_DIR)
for f in p.glob(''**/*.xml''):
new_name = ''{}_{}''.format(f.parent.name, f.name)
f.rename(os.path.join(NEW_DIR, new_name))
Si no tiene una versión moderna de Python (3.5+), también puede usar glob, os y shutil:
import os
import glob
import shutil
for f in glob.glob(''files/**/*.xml''):
new_name = ''{}_{}''.format(os.path.basename(os.path.dirname(f)), os.path.basename(f))
shutil.move(f, os.path.join(''new_dir'', new_name))
Tengo varios archivos en varias carpetas como esta:
dir
├── 0
│ ├── 103425.xml
│ ├── 105340.xml
│ ├── 109454.xml
│
│── 1247
│ └── doc.xml
├── 14568
│ └── doc.xml
├── 1659
│ └── doc.xml
├── 10450
│ └── doc.xml
├── 10351
│ └── doc.xml
¿Cómo puedo extraer todos los documentos en una sola carpeta adjuntando el nombre de la carpeta para cada documento movido?
new_dir
├── 0_103425.xml
├── 0_105340.xml
├── 0_109454.xml
├── 1247_doc.xml
├── 14568_doc.xml
├── 1659_doc.xml
├── 10450_doc.xml
├── 10351_doc.xml
Intenté extraerlos con:
import os
for path, subdirs, files in os.walk(''../dir/''):
for name in files:
print(os.path.join(path, name))
ACTUALIZAR
Además, traté de:
import os, shutil
from glob import glob
files = []
start_dir = os.getcwd()
pattern = "*.xml"
for dir,_,_ in os.walk(''../dir/''):
files.extend(glob(os.path.join(dir,pattern)))
for f in files:
print(f)
shutil.move(f, ''../dir/'')
Lo anterior me dio la ruta de cada archivo. Sin embargo, no entiendo cómo cambiar el nombre y moverlos:
---------------------------------------------------------------------------
Error Traceback (most recent call last)
<ipython-input-50-229e4256f1f3> in <module>()
10 for f in files:
11 print(f)
---> 12 shutil.move(f, ''../dir/'')
/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/shutil.py in move(src, dst, copy_function)
540 real_dst = os.path.join(dst, _basename(src))
541 if os.path.exists(real_dst):
--> 542 raise Error("Destination path ''%s'' already exists" % real_dst)
543 try:
544 os.rename(src, real_dst)
Error: Destination path ''../data/230948.xml'' already exists
El error anterior muestra por qué me gustaría cambiarle el nombre con su carpeta.
Esto es más fácil de hacer con el nuevo módulo pathlib
Python 3 para operaciones de ruta, y luego shutil.move
para mover los archivos a sus lugares correctos. A diferencia de os.rename
, shutil.move
funcionará como el comando mv
y se comportará correctamente incluso para movimientos de sistemas de archivos cruzados.
Este código funcionará para rutas anidadas a cualquier nivel; cualquier /
o /
en las rutas se reemplazará con _
en el nombre de archivo de destino, por lo que dir/foo/bar/baz/xyzzy.xml
se new_dir/foo_bar_baz_xyzzy.xml
a new_dir/foo_bar_baz_xyzzy.xml
.
from pathlib import Path
from shutil import move
src = Path(''dir'')
dst = Path(''new_dir'')
# create the target directory if it doesn''t exist
if not dst.is_dir():
dst.mkdir()
# go through each file
for i in src.glob(''**/*''):
# skip directories and alike
if not i.is_file():
continue
# calculate path relative to `src`,
# this will make dir/foo/bar into foo/bar
p = i.relative_to(src)
# replace path separators with underscore, so foo/bar becomes foo_bar
target_file_name = str(p).replace(''/'', ''_'').replace(''//', ''_'')
# then do rename/move. shutil.move will always do the right thing
# note that it *doesn''t* accept Path objects in Python 3.5, so we
# use str(...) here. `dst` is a path object, and `target_file_name
# is the name of the file to be placed there; we can use the / operator
# instead of os.path.join.
move(str(i), str(dst / target_file_name))