Ver Mensaje Individual
  #6 (permalink)  
Antiguo 26/10/2012, 04:42
vosk
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 12 años, 3 meses
Puntos: 83
Respuesta: funcion rename

"...no siempre se llaman igual los archivos a renombrar..."

ecfisa te ha puesto un ejemplo de como trabajar los nombres y las rutas para ejecutar correctamente el rename, y Fw190 te ha dejado la forma de entrar nombres y rutas a traves de la linea de comandos; tienes que combinarlo un poco: en vez de tener la lista hardcoded de rutas la obtienes de los argumentos de la aplicacion, trabajas los valores para tener las rutas absolutas (la actual y la deseada) y aplicas rename.

El resto depende de como quieras diseñar la entrada de datos pq no hay un estandar (solo sabes que necesitas la ruta original y la ruta deseada, o algo que te permita deducirlo): puedes entrar los datos por pares (origen1 destino1 origen2 destino2...), por tipos (origen1 origen2 destino1 destino2), con modificadores (-p directorio -o nombre_origen -d nombre_destino...), o incluso puedes tirar la casa por la ventana y aceptar un archivo de datos formateado en xml descargado de la red con las rutas de trabajo y los nombres de archivo de origen y destino.

Personalmente usaría el modo grafico (todos los s.o. tienen la api para explorar archivos), pero si no puedes o no quieres usarlo, te propongo que uses modificadores que serían como definiciones previas al dato entrado, de forma que -p implicaría un cambio de directorio, -o sería un nombre de archivo de origen y -d un nombre archivo de destino ademas de punto de ejecucion de rename (son nombres arbitrarios, me los acabo de inventar y no forman parte de ningun estandar ni de nada documentado, en cualquier caso tendrías que documentarlos para distribuir tu propia aplicacion). Supongamos que tu programa se llama 'renombra.exe', está instalado en 'C:/renombra/' y lo ejecutas segun la siguiente cmdl:

renombra.exe -p C:/prueba -o a1.txt -d uno.txt -o a2.txt -d dos.txt

La aplicacion leerá la lista argv encontrando cada elemento (si un mismo elemento contiene espacios necesitará comillas ok? Si estas en C:/mis documentos tendras que indicarlo como "C:/mis documentos" porque el parser de argumentos corta por espacios)

La entrada a la aplicacion es la que te comenta Fw190, ahora tienes que recorrer los elementos comenzando por el 1 (ojo, el indice 1 es el segundo elemento; el primer elemento es el indice 0 y contiene el nombre del ejecutable), ademas tendras que trabajar con pares de datos (el primer será el atributo o llamalo como quieras, y el segundo el dato de trabajo):

Código:
int q;//incremental para el bucle
char *opr, *dat;//operacion y dato
//char cwd[512] = {'\0'};//directorio de trabajo
char org[512] = {'\0'};//ruta origen
char des[512] = {'\0'};//ruta destino

for(q = 1; q < argc; q++) {
    opr = argv[q];
    dat = argv[++q];
}
Ojo, no hay comprovacion de errores (si acaso dejalo para el final) y vamos a suponer que la la cmdl está bien construida. En cada ciclo obtienes una operacion y un dato; sabiendo que las operaciones validas son -p, -o y -d (me las he inventado, son arbitrarias), lo siguiente es diferenciar cada caso; para ello construyes una funcion que te retornará una descripcion inteligible de la accion a ejecutar con los datos disponibles:

Código:
enum modificadores {NADA, PATH, ORIGEN, DESTINO};
int quehago(char *bff) {
    int operacion = NADA;
    
    if(!strcmp("-p", bff)) operacion = PATH;
    else if(!strcmp("-o", bff)) operacion = ORIGEN;
    else if(!strcmp("-d", bff)) operacion = DESTINO;
    
    return operacion;
}
Ok? Ahora en cada bucle llamas a la funcion 'quehago' para saber como manipular el dato segun la operacion asignada:

Código:
switch(quehago(opr)) {
    ....
}
Tienes 4 opciones, en PATH tendras que aplicar un cambio de directorio de trabajo o copiar el dato a la cadena 'cwd' (o una cosa u otra, despues te lo comento con mas detalle), en ORIGEN tendras que copiar el dato a la cadena 'org', en DESTINO tendras que copiar el dato a la cadena 'des' y ejecutar la funcion rename con 'org' y 'des', y por ultimo con NADA no tienes que hacer nada o como mucho mostrar un error de modificador no aceptado o algo por el estilo (si llegas a este NADA sería bueno salir de la aplicacion antes que decrementar el contador 'q' para que no trate esa entrada como par de valores e intentar seguir como si nada).

Ya tienes las acciones, solo has de implementarlas para cada caso:

Código:
case PATH: {
    ...
}
break;
etc...
Para cambiar el directorio de trabajo (cada s.o. tiene su api con las funciones adaptadas) puedes llamar a 'chdir(char *wd)' con la nueva ruta, en el caso PATH tendras algo así:

Código:
chdir(dat);
//getcwd(cwd, sizeof(cwd));
Primero intentas cambiar de directorio (chdir retorna 0 si todo está correcto), o asignas el nuevo directorio a la variable de directorio de trabajo. Observa que en todo el ejemplo te estoy comentando las lineas de la variable del directorio de trabajo 'char cwd[]' porque hay dos formas de hacerlo; si cambias de directorio con 'chdir' no necesitas 'cwd' porque las rutas relativas de los nombres de archivo se aplicaran sobre el directorio de trabajo; si no cambias con chdir tendras que crear las rutas absolutas con la cadena 'cwd' mas la cadena de nombre archivo (origen y destino)

Para el caso ORIGEN, igual de facil, guardas el nombre de origen (o si trabajas sin modificar el directorio tendras que concatenar el nombre de archivo origen a cwd):

Código:
//sprintf(org, "%s\\%s", cwd, dat);//sin chdir
sprintf(org, dat);
Y finalmente DESTINO, parecido a ORIGEN pero haciendo la llamada al rename:

Código:
//sprintf(des, "%s\\%s", cwd, dat);//sin chdir
sprintf(des, dat);
rename(org, des);
Creo que la mejor forma es usando el chdir, te olvidas de la cadena 'cwd' y lo demas está mas claro. Ten en cuenta que el directorio de trabajo es el directorio de trabajo de esa aplicacion y no va a afectar a los demas procesos.

Otra cosa, no he puesto ninguna comprovacion de error, ni para el formato de la cmdl (se espera un modificar valido como segundo elemento, en caso contrario mostrar error y salir) ni para las funciones estandar. Tendrías que implementar esas comprovaciones.

Por cierto, los separadores de directorio \\ son para windows aunque creo que tambien soporta / igual que para los demas s.o.

Saludos
vosk

Última edición por vosk; 26/10/2012 a las 05:05