Utiliza mi proyecto Tasker para principiantes que he creado basándome en esta respuesta . He realizado algunas mejoras significativas que permiten utilizarlo para muchos otros escenarios además de mover las imágenes de Facebook, y he incluido varios ejemplos en el proyecto para aprender de ellos:
- Aunque la versión original podía detectar si el archivo que se estaba moviendo ya existía en el directorio de destino, sólo podía manejar una iteración del conflicto. Por ejemplo, si se estaba moviendo ejemplo.jpg, pero ya existía, renombraría el archivo que se estaba moviendo a ejemplo(1).jpg. Sin embargo, si se moviera ejemplo.jpg y tanto ejemplo.jpg como ejemplo(1).jpg ya existieran, simplemente sobrescribiría ejemplo(1).jpg.
- Mi versión ejecutará una comprobación iterativa de los nombres que incrementará la variable sufijo hasta que se encuentre un nombre inexistente. Por ejemplo, si se toma ejemplo.jpg, comprobará ejemplo(2).jpg. Si está ocupado, comprobará ejemplo(3).jpg, y así sucesivamente hasta que encuentre un nombre disponible. También añade correctamente el primer duplicado con (2) en lugar de (1).
- La versión original asumía que el primer "." de un nombre de archivo era también el último "." antes de la extensión. Si bien esto está bien para las imágenes de Facebook, no es una suposición ideal, y se rompe cuando la adopción de la tarea para otros usos, tales como APKs en movimiento. Con el original, si com.ejemplo.app.apk ya existía en el directorio de destino, al intentar mover una segunda copia de la misma resultaría com(1).ejemplo.app.apk.
- Además de arreglar el sufijo y hacerlo iterativo, también he cambiado la lógica para su colocación, de forma que siempre irá antes del último ".". En el ejemplo anterior, el apk pasaría a llamarse com.ejemplo.app(2).apk. Esto no siempre funciona a la perfección (considere .tar.gz y otros casos similares, por ejemplo), pero hace un trabajo lo suficientemente bueno sin tener que codificar todas las extensiones posibles.
- Esto parece variar de un dispositivo a otro, pero en mis dispositivos, la versión original dejaba referencias rotas a las imágenes en aplicaciones de galería y otros programas que utilizan el proveedor multimedia (la mayoría de las aplicaciones de mensajería que tienen una interfaz de usuario de selección de imágenes) debido a que no se actualizaban correctamente estos datos. Esto no era un problema para mover imágenes fuera de un directorio que contenga un archivo .nomedia, pero causaba problemas si querías usarlo en un directorio donde no querías o no podías tener un archivo .nomedia (como mover automáticamente imágenes descargadas fuera de /sdcard/Download/).
- La acción Scan Media de Tasker parece actuar de formas muy diferentes dependiendo no sólo de la versión de Android, sino también de la variante del proveedor que estés utilizando. He solucionado el problema en mis dispositivos (y espero que muchos de los suyos) mediante la ejecución de una acción Scan Media no sólo en el archivo en su directorio de destino, sino también en la ruta del archivo original (haciendo referencia al archivo que ya no está allí).
También he actualizado los nombres de las variables para mayor claridad, y en lugar de utilizar eventos que se activan al entrar o salir de las aplicaciones, lo he configurado para que se ejecute en un evento de Archivo Modificado que monitoriza la carpeta de origen, con el evento configurado como Escritura Cerrada. Esto funciona para la mayoría de los propósitos, pero se rompe en algunos casos. Puede solucionar la mayoría de los problemas utilizando un parámetro de evento diferente (como Crear, Modificar o Mover a) o utilizando una expresión regular más estricta en la Acción 3 de la tarea.
He oído que los dispositivos con almacenamiento más lento (o tarjetas SD externas lentas) pueden tener problemas con esto si los archivos tardan demasiado en escribirse. En ese caso, puede que tenga que experimentar con la adición de retrasos o el uso de diferentes métodos para desencadenar la tarea.
Estoy adjuntando no sólo la tarea aquí, sino todo el proyecto que he creado, que contiene múltiples copias de la tarea para diversos casos de uso, y sus respectivos perfiles para desencadenarlos, para que los principiantes que son nuevos en Tasker puedan empezar fácilmente a utilizar esta tarea y tener algunos ejemplos de referencia a la hora de adoptar la tarea a sus propias necesidades.
Los ejemplos incluidos en este proyecto son:
- Cuando Facebook descargue una imagen en /sdcard/DCIM/Facebook, muévela a /sdcard/Pictures/Facebook.
- Cuando Samsung Notes guarde una imagen en /sdcard/DCIM/Samsung Notes/, muévala a /sdcard/Pictures/Samsung Notes/. (Esto funciona, pero Samsung Notes dirá que no ha podido guardar la imagen, debido a que la busca después de que Tasker ya la haya movido).
- Cuando cree un GIF utilizando Smart Select, muévalo de /sdcard/DCIM/GIF/ a /sdcard/Pictures/Smart Select GIFs/.
- Cuando exportes un APK desde ReVanced Manager a /sdcard/Download/APKs/Original/, muévelo a /sdcard/Download/APKs/Modded/.
- Cuando se detecta un nuevo archivo en /sdcard/Download/ . . .
- si se trata de una descarga desde Craiyon Muévelo a /sdcard/Pictures/Craiyon/
- si se trata de un archivo APK, APKM, APKS o XAPK, muévelo a /sdcard/Download/APKs/Original, a menos que es base.apk (dejo ese archivo en Download ya que lo uso para otras cosas).
Recuerda crear primero los directorios de origen y destino antes de probar los ejemplos. También te animo a que compruebes la Acción 3 en cada tarea de ejemplo (algunas de ellas utilizan simple matching y otras regex) para una mejor comprensión de su funcionamiento.
Ahora que eso está fuera del camino, aquí es el proyecto. Puedes importarlo directamente a Tasker desde ahí, o descargarlo como un XML. Si eliges descargarlo, guárdalo en /sdcard/Tasker/projects/. A continuación, puedes hacer una pulsación larga en el icono de inicio de la esquina inferior izquierda de Tasker para importar el proyecto.
Lamentablemente, el XML completo es demasiado largo para publicarlo aquí directamente, pero para que esta respuesta sea lo más completa posible, incluyo el XML de sólo la tarea de Facebook a continuación. Sin embargo, recomiendo encarecidamente a los principiantes que importen el proyecto completo utilizando el enlace anterior, para que puedan hacerse una idea de cómo personalizar la tarea para sus propias necesidades.
La tarea de Facebook:
<TaskerData sr="" dvi="1" tv="6.0.10">
<Task sr="task3">
<cdate>1489093858387</cdate>
<edate>1677367714628</edate>
<id>3</id>
<nme>Move Facebook Images</nme>
<pri>6</pri>
<Kid sr="Kid">
<launchID>3</launchID>
<pkg>me.regalstreak.movefb</pkg>
<vTarg>21</vTarg>
<vnme>1.0</vnme>
</Kid>
<Action sr="act0" ve="7">
<code>547</code>
<Str sr="arg0" ve="3">%sourcedir</Str>
<Str sr="arg1" ve="3">/sdcard/DCIM/Facebook/</Str>
<Int sr="arg2" val="0"/>
<Int sr="arg3" val="0"/>
<Int sr="arg4" val="0"/>
<Int sr="arg5" val="3"/>
<Int sr="arg6" val="0"/>
</Action>
<Action sr="act1" ve="7">
<code>547</code>
<Str sr="arg0" ve="3">%destdir</Str>
<Str sr="arg1" ve="3">/sdcard/Pictures/Facebook/</Str>
<Int sr="arg2" val="0"/>
<Int sr="arg3" val="0"/>
<Int sr="arg4" val="0"/>
<Int sr="arg5" val="3"/>
<Int sr="arg6" val="0"/>
</Action>
<Action sr="act10" ve="7">
<code>37</code>
<ConditionList sr="if">
<Condition sr="c0" ve="3">
<lhs>%fileexists</lhs>
<op>12</op>
<rhs></rhs>
</Condition>
</ConditionList>
</Action>
<Action sr="act11" ve="7">
<code>547</code>
<Str sr="arg0" ve="3">%currentfilename</Str>
<Str sr="arg1" ve="3">%currentfilepath(%pathlen)</Str>
<Int sr="arg2" val="0"/>
<Int sr="arg3" val="0"/>
<Int sr="arg4" val="0"/>
<Int sr="arg5" val="3"/>
<Int sr="arg6" val="0"/>
</Action>
<Action sr="act12" ve="7">
<code>888</code>
<Str sr="arg0" ve="3">%suffix</Str>
<Int sr="arg1" val="1"/>
<Int sr="arg2" val="0"/>
</Action>
<Action sr="act13" ve="7">
<code>590</code>
<Str sr="arg0" ve="3">%currentfilename</Str>
<Str sr="arg1" ve="3">.</Str>
<Int sr="arg2" val="0"/>
<Int sr="arg3" val="0"/>
</Action>
<Action sr="act14" ve="7">
<code>547</code>
<Str sr="arg0" ve="3">%namelen</Str>
<Str sr="arg1" ve="3">%currentfilename(#)</Str>
<Int sr="arg2" val="0"/>
<Int sr="arg3" val="0"/>
<Int sr="arg4" val="0"/>
<Int sr="arg5" val="3"/>
<Int sr="arg6" val="0"/>
</Action>
<Action sr="act15" ve="7">
<code>890</code>
<Str sr="arg0" ve="3">%namelen</Str>
<Int sr="arg1" val="1"/>
<Int sr="arg2" val="0"/>
</Action>
<Action sr="act16" ve="7">
<code>547</code>
<Str sr="arg0" ve="3">%currentfilename(%namelen)</Str>
<Str sr="arg1" ve="3">%currentfilename(%namelen)%null()(%suffix)</Str>
<Int sr="arg2" val="0"/>
<Int sr="arg3" val="0"/>
<Int sr="arg4" val="0"/>
<Int sr="arg5" val="3"/>
<Int sr="arg6" val="0"/>
</Action>
<Action sr="act17" ve="7">
<code>592</code>
<Str sr="arg0" ve="3">%currentfilename</Str>
<Str sr="arg1" ve="3">.</Str>
<Int sr="arg2" val="0"/>
</Action>
<Action sr="act18" ve="7">
<code>135</code>
<Int sr="arg0" val="0"/>
<Int sr="arg1" val="10"/>
<Str sr="arg2" ve="3"/>
</Action>
<Action sr="act19" ve="7">
<code>38</code>
</Action>
<Action sr="act2" ve="7">
<code>412</code>
<Str sr="arg0" ve="3">%sourcedir</Str>
<Str sr="arg1" ve="3">*.jpg/*.png/*.jpeg/*.gif/*.3gp</Str>
<Int sr="arg2" val="0"/>
<Int sr="arg3" val="0"/>
<Int sr="arg4" val="0"/>
<Str sr="arg5" ve="3">%filelist</Str>
<Int sr="arg6" val="1"/>
</Action>
<Action sr="act20" ve="7">
<code>400</code>
<Str sr="arg0" ve="3">%currentfilepath</Str>
<Str sr="arg1" ve="3">%destdir%currentfilename</Str>
<Int sr="arg2" val="0"/>
<Int sr="arg3" val="1"/>
</Action>
<Action sr="act21" ve="7">
<code>459</code>
<Str sr="arg0" ve="3">%currentfilepath</Str>
</Action>
<Action sr="act22" ve="7">
<code>459</code>
<Str sr="arg0" ve="3">%destdir%currentfilename</Str>
</Action>
<Action sr="act23" ve="7">
<code>888</code>
<Str sr="arg0" ve="3">%counter</Str>
<Int sr="arg1" val="1"/>
<Int sr="arg2" val="0"/>
</Action>
<Action sr="act24" ve="7">
<code>40</code>
</Action>
<Action sr="act25" ve="7">
<code>37</code>
<ConditionList sr="if">
<Condition sr="c0" ve="3">
<lhs>%counter</lhs>
<op>0</op>
<rhs>0</rhs>
</Condition>
</ConditionList>
</Action>
<Action sr="act26" ve="7">
<code>548</code>
<Str sr="arg0" ve="3">No memes? Sad.</Str>
<Int sr="arg1" val="0"/>
<Str sr="arg10" ve="3"/>
<Int sr="arg11" val="1"/>
<Int sr="arg12" val="0"/>
<Str sr="arg13" ve="3"/>
<Int sr="arg14" val="0"/>
<Int sr="arg2" val="0"/>
<Str sr="arg3" ve="3"/>
<Str sr="arg4" ve="3"/>
<Str sr="arg5" ve="3"/>
<Str sr="arg6" ve="3"/>
<Str sr="arg7" ve="3"/>
<Str sr="arg8" ve="3"/>
<Int sr="arg9" val="1"/>
</Action>
<Action sr="act27" ve="7">
<code>43</code>
<ConditionList sr="if">
<Condition sr="c0" ve="3">
<lhs>%counter</lhs>
<op>0</op>
<rhs>1</rhs>
</Condition>
</ConditionList>
</Action>
<Action sr="act28" ve="7">
<code>548</code>
<Str sr="arg0" ve="3">%counter meme moved!</Str>
<Int sr="arg1" val="0"/>
<Str sr="arg10" ve="3"/>
<Int sr="arg11" val="1"/>
<Int sr="arg12" val="0"/>
<Str sr="arg13" ve="3"/>
<Int sr="arg14" val="0"/>
<Int sr="arg2" val="0"/>
<Str sr="arg3" ve="3"/>
<Str sr="arg4" ve="3"/>
<Str sr="arg5" ve="3"/>
<Str sr="arg6" ve="3"/>
<Str sr="arg7" ve="3"/>
<Str sr="arg8" ve="3"/>
<Int sr="arg9" val="1"/>
</Action>
<Action sr="act29" ve="7">
<code>43</code>
</Action>
<Action sr="act3" ve="7">
<code>547</code>
<Str sr="arg0" ve="3">%suffix</Str>
<Str sr="arg1" ve="3">1</Str>
<Int sr="arg2" val="0"/>
<Int sr="arg3" val="0"/>
<Int sr="arg4" val="0"/>
<Int sr="arg5" val="3"/>
<Int sr="arg6" val="0"/>
</Action>
<Action sr="act30" ve="7">
<code>548</code>
<Str sr="arg0" ve="3">%counter memes moved!</Str>
<Int sr="arg1" val="0"/>
<Str sr="arg10" ve="3"/>
<Int sr="arg11" val="1"/>
<Int sr="arg12" val="0"/>
<Str sr="arg13" ve="3"/>
<Int sr="arg14" val="0"/>
<Int sr="arg2" val="0"/>
<Str sr="arg3" ve="3"/>
<Str sr="arg4" ve="3"/>
<Str sr="arg5" ve="3"/>
<Str sr="arg6" ve="3"/>
<Str sr="arg7" ve="3"/>
<Str sr="arg8" ve="3"/>
<Int sr="arg9" val="1"/>
</Action>
<Action sr="act4" ve="7">
<code>547</code>
<Str sr="arg0" ve="3">%counter</Str>
<Str sr="arg1" ve="3">0</Str>
<Int sr="arg2" val="0"/>
<Int sr="arg3" val="1"/>
<Int sr="arg4" val="0"/>
<Int sr="arg5"/>
<Int sr="arg6" val="0"/>
</Action>
<Action sr="act5" ve="7">
<code>39</code>
<coll>false</coll>
<Str sr="arg0" ve="3">%currentfilepath</Str>
<Str sr="arg1" ve="3">%filelist()</Str>
<Int sr="arg2" val="0"/>
</Action>
<Action sr="act6" ve="7">
<code>590</code>
<Str sr="arg0" ve="3">%currentfilepath</Str>
<Str sr="arg1" ve="3">/</Str>
<Int sr="arg2" val="0"/>
<Int sr="arg3" val="0"/>
</Action>
<Action sr="act7" ve="7">
<code>547</code>
<Str sr="arg0" ve="3">%pathlen</Str>
<Str sr="arg1" ve="3">%currentfilepath(#)</Str>
<Int sr="arg2" val="0"/>
<Int sr="arg3" val="0"/>
<Int sr="arg4" val="0"/>
<Int sr="arg5" val="3"/>
<Int sr="arg6" val="0"/>
</Action>
<Action sr="act8" ve="7">
<code>547</code>
<Str sr="arg0" ve="3">%currentfilename</Str>
<Str sr="arg1" ve="3">%currentfilepath(%pathlen)</Str>
<Int sr="arg2" val="0"/>
<Int sr="arg3" val="0"/>
<Int sr="arg4" val="0"/>
<Int sr="arg5" val="3"/>
<Int sr="arg6" val="0"/>
</Action>
<Action sr="act9" ve="7">
<code>342</code>
<se>false</se>
<Int sr="arg0" val="4"/>
<Str sr="arg1" ve="3">%destdir%currentfilename</Str>
<Str sr="arg2" ve="3">%fileexists</Str>
<Int sr="arg3" val="0"/>
<Int sr="arg4" val="1"/>
</Action>
<Img sr="icn" ve="2">
<cls>com.facebook.katana.LoginActivity</cls>
<pkg>com.facebook.katana</pkg>
</Img>
</Task>
</TaskerData>