<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Friedrich Ruiz</title>
    <description>The latest articles on Forem by Friedrich Ruiz (@fiedric).</description>
    <link>https://forem.com/fiedric</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3585025%2F95cc9ea7-8811-4d86-9b4f-d08e9fffc550.jpeg</url>
      <title>Forem: Friedrich Ruiz</title>
      <link>https://forem.com/fiedric</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/fiedric"/>
    <language>en</language>
    <item>
      <title>¿Cómo apagué la música de una fiesta para poder dormir?</title>
      <dc:creator>Friedrich Ruiz</dc:creator>
      <pubDate>Sun, 21 Dec 2025 02:43:51 +0000</pubDate>
      <link>https://forem.com/fiedric/como-apague-la-musica-de-una-fiesta-para-poder-dormir-2p06</link>
      <guid>https://forem.com/fiedric/como-apague-la-musica-de-una-fiesta-para-poder-dormir-2p06</guid>
      <description>&lt;p&gt;Creo que una de las cosas que más me causó indignación este año fue que haya parranda en mi refugio temporal (la casa donde vivo), no estar invitado y tener que calarme la música y la gente cantando karaoke hasta tarde. Todo esto sacrificando mis valiosas horas de sueño por pura obstinación ajena.&lt;/p&gt;

&lt;p&gt;Hasta que recordé que soy informático. Me pregunté qué podía hacer con este vasto conocimiento en las artes digitales y recordé que hace tiempo había probado un script para realizar &lt;strong&gt;Bluesmack&lt;/strong&gt; (un ataque de denegación de servicio a dispositivos Bluetooth). Mi primera idea fue imponer mi poder como hacker silenciando el receptor directamente. Sin embargo, encontrar la dirección MAC del radio fue imposible; tras tres horas de búsqueda fallida, escuché un anuncio de YouTube saliendo por las cornetas.&lt;/p&gt;

&lt;p&gt;Eso lo cambió todo. Significaba que no dependían solo del Bluetooth, sino que usaban el Wi-Fi para su música mundana. En ese momento entendí que mi objetivo de dormir aún no estaba perdido.&lt;/p&gt;




&lt;h2&gt;
  
  
  Paso 1: Localización y Reconocimiento de Red
&lt;/h2&gt;

&lt;p&gt;Para atacar, primero necesitaba un mapa de mi red local. El primer paso fue identificar la &lt;strong&gt;IP del Router&lt;/strong&gt;. Utilicé el comando:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ip route show&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Este comando devuelve la tabla de enrutamiento del sistema. La línea que nos interesa es la que comienza con &lt;code&gt;default via&lt;/code&gt;, que indica la dirección del nodo central:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Ejemplo de salida:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;default via 192.168.0.1 dev wlx88947e9b4dab proto dhcp metric 600&lt;/code&gt;&lt;br&gt;
&lt;em&gt;Aquí confirmamos que el router es la IP **192.168.0.1&lt;/em&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Con la dirección del router clara, utilicé &lt;strong&gt;Nmap&lt;/strong&gt; para realizar un escaneo de dispositivos activos en el segmento de red (&lt;code&gt;/24&lt;/code&gt; que abarca de la IP .1 a la .254):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo nmap -sn 192.168.0.0/24&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;El parámetro &lt;code&gt;-sn&lt;/code&gt; indica un "Ping Scan", que detecta dispositivos encendidos sin realizar un escaneo de puertos profundo, lo que lo hace mucho más rápido.&lt;/p&gt;




&lt;h2&gt;
  
  
  Intento 1: Inundación por ICMP (Ping Flood)
&lt;/h2&gt;

&lt;p&gt;Con la lista de sospechosos en mano (excluyendo mi PC y el router), identifiqué los teléfonos que estaban haciendo el streaming. Mi primer movimiento fue un &lt;strong&gt;Ping Flood&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo ping -f &amp;lt;ip_del_dispositivo&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;El parámetro &lt;code&gt;-f&lt;/code&gt; (flood) envía paquetes ICMP tan rápido como el sistema puede procesarlos o tan pronto como regresan. Ejecuté esto en varias terminales simultáneamente contra distintas IPs sospechosas. Aunque la música presentaba interrupciones, el streaming lograba recuperarse debido a que los routers modernos tienen mecanismos para priorizar o limitar este tipo de tráfico básico.&lt;/p&gt;




&lt;h2&gt;
  
  
  Intento 2: Ataque Man-In-The-Middle (ARP Spoofing)
&lt;/h2&gt;

&lt;p&gt;Decidí escalar el ataque mediante una técnica de &lt;strong&gt;Envenenamiento de Tablas ARP&lt;/strong&gt;. El objetivo era engañar al router para que pensara que mi PC era el teléfono, y al teléfono para que pensara que mi PC era el router.&lt;/p&gt;

&lt;p&gt;Utilicé la herramienta &lt;strong&gt;arpspoof&lt;/strong&gt; en dos terminales:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;sudo arpspoof -i interfaz -t 192.168.0.109 192.168.0.1&lt;/code&gt; (Engañando al teléfono).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo arpspoof -i interfaz -t 192.168.0.1 192.168.0.109&lt;/code&gt; (Engañando al router).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Al interceptar el tráfico, simplemente desactivé el reenvío de paquetes en mi kernel (&lt;code&gt;ip_forward=0&lt;/code&gt;), convirtiendo mi pc en un "agujero negro" para sus datos. Sin embargo, mi tarjeta de red inalámbrica no soportó el volumen de paquetes y el ataque no fue persistente.&lt;/p&gt;




&lt;h2&gt;
  
  
  Intento 3: Saturación de Capa 4 (TCP SYN Flood), la tercera es la vencida.
&lt;/h2&gt;

&lt;p&gt;Al ver que los métodos anteriores fallaban, utilicé uno mas rudo: &lt;strong&gt;hping3&lt;/strong&gt;. A diferencia del ping común (Capa 3), este ataque se enfoca en la Capa de Transporte (Capa 4), específicamente en el protocolo &lt;strong&gt;TCP&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo hping3 -S -p 80 --flood 192.168.0.120&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué funcionó este método?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Modo Flood:&lt;/strong&gt; Envía paquetes a la máxima velocidad posible sin esperar respuesta, saturando el ancho de banda.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flag SYN (&lt;code&gt;-S&lt;/code&gt;):&lt;/strong&gt; Envía peticiones de inicio de conexión. El dispositivo de la víctima se ve obligado a reservar memoria para cada conexión falsa que yo inicio. Al recibir millones de estas peticiones, el procesador del teléfono colapsa intentando gestionarlas todas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Puerto 80:&lt;/strong&gt; Al atacar el puerto estándar de navegación web, el dispositivo no puede ignorar el tráfico fácilmente.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;El resultado fue inmediato: el teléfono de los invitados se quedó sin recursos para mantener la conexión de YouTube. La música se cortó definitivamente y, ante la frustración de no tener conexión, finalmente apagaron el radio. La victoria fue mía. &lt;em&gt;Procede a reírse como un villano.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>¿Qué es la Terminal, la Línea de Comandos (CLI) y el Shell?</title>
      <dc:creator>Friedrich Ruiz</dc:creator>
      <pubDate>Tue, 18 Nov 2025 02:01:08 +0000</pubDate>
      <link>https://forem.com/fiedric/que-es-la-terminal-la-linea-de-comandos-cli-y-el-shell-2808</link>
      <guid>https://forem.com/fiedric/que-es-la-terminal-la-linea-de-comandos-cli-y-el-shell-2808</guid>
      <description>&lt;p&gt;Mucha gente usa los términos "terminal", "línea de comandos" y "shell" como si fueran lo mismo, pero no lo son. Entender la diferencia es clave para saber qué estás haciendo realmente.&lt;/p&gt;

&lt;p&gt;Vamos a aclararlo con una analogía simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;La Terminal&lt;/strong&gt; es la &lt;em&gt;aplicación&lt;/em&gt; que abres. Es la "ventana" (como el Terminal de Windows, iTerm2 en Mac, o GNOME Terminal en Linux).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;El Shell&lt;/strong&gt; es el &lt;em&gt;programa&lt;/em&gt; que corre &lt;em&gt;dentro&lt;/em&gt; de la terminal. Es el "cerebro" que interpreta tus comandos (ej: &lt;code&gt;bash&lt;/code&gt;, &lt;code&gt;zsh&lt;/code&gt;, &lt;code&gt;fish&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;La Línea de Comandos (CLI)&lt;/strong&gt; es el &lt;em&gt;método&lt;/em&gt; de interactuar. Es la interfaz (la pantalla negra con un cursor) donde escribes texto. Es lo opuesto a una GUI (Interfaz Gráfica de Usuario) donde usas un mouse.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En resumen: Abres la &lt;strong&gt;Terminal&lt;/strong&gt; para usar un &lt;strong&gt;Shell&lt;/strong&gt; a través de su &lt;strong&gt;Línea de Comandos&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  El Shell: El Intérprete de Comandos
&lt;/h2&gt;

&lt;p&gt;Cuando escribes un comando, la terminal no lo entiende. Simplemente pasa ese texto al Shell. El Shell es el programa que lee el comando, lo interpreta y le dice al sistema operativo (Linux, macOS, etc.) qué hacer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bash (Bourne Again SHell)
&lt;/h2&gt;

&lt;p&gt;La terminal que venia por defecto en la mayoría de sistemas Linux y macOS durante décadas. Es el estándar de la industria.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comandos Básicos de Bash
&lt;/h3&gt;

&lt;p&gt;Aquí tienes los comandos esenciales para moverte.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pwd&lt;/code&gt; (Print Working Directory): Imprime el directorio (carpeta) actual donde estás trabajando.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cd&lt;/code&gt; (Change Directory): Te permite cambiar de directorio.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cd nombre_carpeta&lt;/code&gt; (Entra a una carpeta)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cd ..&lt;/code&gt; (Sube un nivel, al directorio padre)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cd ~&lt;/code&gt; o solo &lt;code&gt;cd&lt;/code&gt; (Te lleva a tu directorio "Home" o principal)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;ls&lt;/code&gt; (List): Lista el contenido de la carpeta de trabajo actual.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ls -a&lt;/code&gt; (Muestra &lt;em&gt;todos&lt;/em&gt; los archivos, incluyendo los ocultos como &lt;code&gt;.env&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ls -l&lt;/code&gt; (Muestra la "lista larga", con permisos, dueño, tamaño y fecha).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;cat&lt;/code&gt; vs &lt;code&gt;less&lt;/code&gt;: Para ver el contenido de un archivo.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cat archivo.txt&lt;/code&gt;: Imprime &lt;em&gt;todo&lt;/em&gt; el contenido del archivo en la terminal. Es rápido, pero inútil si el archivo es muy largo.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;less archivo.txt&lt;/code&gt;: Es un "paginador". Te permite ver el contenido de archivos grandes de forma interactiva (puedes subir, bajar y buscar). Es mucho más útil.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;mkdir&lt;/code&gt; (Make Directory): Permite crear carpetas (ej: &lt;code&gt;mkdir nuevaCarpeta&lt;/code&gt;).&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;touch&lt;/code&gt;: Crea un archivo nuevo y vacío (ej: &lt;code&gt;touch readme.md&lt;/code&gt;).&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;mv&lt;/code&gt; (Move): Te permite mover un archivo O renombrarlo.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;mv archivo.txt /otra/carpeta/&lt;/code&gt; (Mover)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mv archivo_viejo.txt archivo_nuevo.txt&lt;/code&gt; (Renombrar)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;cp&lt;/code&gt; (Copy): Copia un archivo o directorio. A diferencia de &lt;code&gt;mv&lt;/code&gt;, no elimina el original.

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cp archivo.txt /otra/carpeta/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cp -r mi_directorio /otra/carpeta/&lt;/code&gt; (Para copiar un directorio, necesitas el argumento &lt;code&gt;-r&lt;/code&gt; de "recursivo").&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;rm&lt;/code&gt; (Remove): Elimina un archivo.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;rm -r mi_directorio/&lt;/code&gt; (Elimina una carpeta y todo lo que tiene dentro).&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;¡ADVERTENCIA!&lt;/em&gt; &lt;code&gt;rm&lt;/code&gt; no tiene "papelera de reciclaje". Una vez que lo usas, la información se pierde. Ten mucho cuidado, especialmente con &lt;code&gt;rm -rf&lt;/code&gt; (&lt;code&gt;-f&lt;/code&gt; fuerza la eliminación sin preguntar), ya que es un comando muy destructivo.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;echo&lt;/code&gt;: Toma un argumento de texto (string) y lo imprime en la terminal. Es muy útil para crear o añadir texto a archivos.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;echo "Hola" &amp;gt; readme.md&lt;/code&gt; (Crea o &lt;strong&gt;sobrescribe&lt;/strong&gt; el archivo).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;echo "Adios" &amp;gt;&amp;gt; readme.md&lt;/code&gt; (Usa &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; para &lt;strong&gt;agregar&lt;/strong&gt; al final del archivo).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;man&lt;/code&gt; (Manual): Muestra el manual de cualquier comando.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;man ls&lt;/code&gt; (Te mostrará todas las opciones posibles para &lt;code&gt;ls&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Qué son las Opciones y Argumentos?
&lt;/h2&gt;

&lt;p&gt;Puedes pasarle argumentos (parámetros) u opciones (flags) a un comando para afectar la manera en la que actúa.&lt;/p&gt;

&lt;h3&gt;
  
  
  2 Guiones (Forma Larga o "Human-Readable")
&lt;/h3&gt;

&lt;p&gt;Son fáciles de entender. Por ejemplo, &lt;code&gt;ls --all&lt;/code&gt; es lo mismo que &lt;code&gt;ls -a&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1 Guion (Forma Corta o "POSIX")
&lt;/h3&gt;

&lt;p&gt;Usan una sola letra. La gran ventaja es que permite "encadenar" múltiples argumentos.&lt;/p&gt;

&lt;p&gt;En lugar de escribir:&lt;br&gt;
&lt;code&gt;ls --all --human-readable --size&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Puedes agruparlos de la siguiente manera:&lt;br&gt;
&lt;code&gt;ls -ahs&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Control de Procesos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Ctrl+C&lt;/code&gt; (Interrumpir): "Mata" o detiene el proceso que se está ejecutando en primer plano (ej: un script).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl+Z&lt;/code&gt; (Suspender): "congela" el proceso actual y lo envía al &lt;em&gt;background&lt;/em&gt; (segundo plano). Puedes ver los procesos suspendidos con &lt;code&gt;jobs&lt;/code&gt; y traerlos de vuelta con &lt;code&gt;fg&lt;/code&gt; (foreground).&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>notasconceptuales</category>
    </item>
    <item>
      <title>Organizador de carpetas hecho en python</title>
      <dc:creator>Friedrich Ruiz</dc:creator>
      <pubDate>Fri, 07 Nov 2025 05:02:04 +0000</pubDate>
      <link>https://forem.com/fiedric/organizador-de-carpetas-hecho-en-python-56h8</link>
      <guid>https://forem.com/fiedric/organizador-de-carpetas-hecho-en-python-56h8</guid>
      <description>&lt;p&gt;Seguramente al abrir tu carpeta de descargas o cualquier otra te encuentras con una cantidad incontable de archivos de diferente tipos (imagenes, documentos, instaladores, etc) mezclados y te ha tocado buscar desesperadamente ese pdf que contiene la tarea que te hizo &lt;strong&gt;chatgpt&lt;/strong&gt;, tardando un tiempo considerable y pensando &lt;em&gt;'que flojera'&lt;/em&gt;, o teniendo que ordenar 20 pdf, 10 imagenes y 5 instaladores manualmente. Yo tambien habia pasado por esto, y por eso decedí crear un script que me permitiera seguir vagueando mientras mis archivos estan perfectamente ordenados.&lt;br&gt;
Este script que utiliza python hace ese trabajo por mi. Puedes verlo directamente &lt;a href="https://github.com/fiedri/fiedric-toolbox/blob/master/organizador%20de%20archivos/src/organizer_downloads_auto.py" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Como funciona el script
&lt;/h2&gt;

&lt;p&gt;Para construir esta herramienta use varias librerias de Python, algunas que ya vienen incluidas ("biblioteca éxtandar") y una externa para que me notifique cuando el script se esta ejecutando.&lt;/p&gt;
&lt;h3&gt;
  
  
  Paso 1: las importaciones
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;shutil&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;win10toast&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ToastNotifier&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;os&lt;/code&gt; (Operating System): Nos permite verificar si un archivo o carpeta existe (&lt;code&gt;os.path.exists&lt;/code&gt;), crear carpetas (&lt;code&gt;os.makedirs&lt;/code&gt;), listar todos los archivos (&lt;code&gt;os.listdir&lt;/code&gt;) y obtener la extensión de un archivo (&lt;code&gt;os.path.splitext&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shutil&lt;/code&gt; (Shell Utilities): Nos permite mover archivos de un lugar a otro (&lt;code&gt;shutil.move()&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sys&lt;/code&gt; (System): &lt;code&gt;sys.executable&lt;/code&gt; me permite saber dónde se está ejecutando el script, lo cual es muy útil si se compila en un archivo .exe.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ToastNotifier&lt;/code&gt; (de &lt;code&gt;win10toast&lt;/code&gt;): Esta es la librería externa. Es la que nos permite enviar notificaciones nativas a Windows. Se instala con &lt;code&gt;pip install wintoast&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Paso 2: Mapa de archivos
&lt;/h3&gt;

&lt;p&gt;Se crea un diccionario que actúa como un mapa, donde cada clave es el nombre de la carpeta que queremos crear (ej. "imagenes") y el valor es una lista de todas las extensiones de archivo que deben ir dentro de dicha carpeta.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;notificar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ToastNotifier&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# Inicializamos el notificador
&lt;/span&gt;&lt;span class="n"&gt;tipos_de_archivo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;imagenes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.jpeg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.gif&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.bmp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.svg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;videos&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.avi&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.mov&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.mkv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.webm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;documentos&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.pdf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.doc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.docx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.xls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.xlsx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ejecutables y sistema&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.exe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.msi&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.bat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.dll&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;comprimidos&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.zip&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.rar&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.7z&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.iso&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="c1"&gt;# ...y así con todas las demás categorías...
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Otros&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="c1"&gt;# Una categoría especial para lo que no coincida
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Paso 3: Configuración Flexible (Leer el rutas.txt)
&lt;/h3&gt;

&lt;p&gt;No quería editar el script cada vez que quisiera añadir una carpeta nueva para organizar. Por eso, hice que el script leyera un archivo de configuración &lt;code&gt;rutas.txt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Esta función abre ese archivo, lee cada línea, y si la ruta escrita existe de verdad, la añade a una lista.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;obtener_rutas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta_actual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;archivo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rutas.txt&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Obtener rutas escritas en el archivo config/rutas.txt
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;rutas_validas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="c1"&gt;# Busca el archivo .txt en una carpeta 'config'
&lt;/span&gt;    &lt;span class="n"&gt;archivo_rutas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta_actual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;config&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;archivo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;archivo_rutas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;rutas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;linea&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rutas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;ruta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linea&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# .strip() quita espacios en blanco
&lt;/span&gt;            &lt;span class="c1"&gt;# Si la ruta no está vacía Y existe...
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ruta&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;rutas_validas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abspath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;rutas_validas&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Paso 4: Manejo de duplicados
&lt;/h3&gt;

&lt;p&gt;Esta es la parte más importante. ¿Qué pasa si muevo &lt;code&gt;tarea.pdf&lt;/code&gt; a "Documentos" y ya existe un &lt;code&gt;tarea.pdf&lt;/code&gt; dentro?&lt;/p&gt;

&lt;p&gt;Para eso, esta la función mover_archivo.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Intenta moverlo: Si el archivo no existe en el &lt;strong&gt;destino&lt;/strong&gt;, simplemente lo mueve (&lt;code&gt;shutil.move&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Si ya existe:&lt;/p&gt;

&lt;p&gt;1- Crea una carpeta llamada "DUPLICADOS".&lt;br&gt;
2- Le cambia el nombre al archivo nuevo (ej. de &lt;code&gt;tarea.pdf&lt;/code&gt; a &lt;code&gt;tarea (1).pdf&lt;/code&gt;).&lt;br&gt;
3- Busca un nombre libre (si &lt;code&gt;tarea (1).pdf&lt;/code&gt; existe, prueba con &lt;code&gt;tarea (2).pdf&lt;/code&gt;, y así...).&lt;br&gt;
4- Mueve el archivo renombrado a la carpeta "DUPLICADOS".&lt;br&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mover_archivo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;origen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destino&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;destino&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="c1"&gt;# Ruta libre, mover normalmente
&lt;/span&gt;            &lt;span class="n"&gt;shutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;origen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destino&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# ¡Conflicto! El archivo ya existe
&lt;/span&gt;            &lt;span class="n"&gt;carpeta_duplicados&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;destino&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DUPLICADOS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carpeta_duplicados&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Lógica para encontrar un nuevo nombre (ej. "archivo (1).ext")
&lt;/span&gt;            &lt;span class="n"&gt;contador&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;origen&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;nuevo_nombre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;contador&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;nuevo_destino&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carpeta_duplicados&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nuevo_nombre&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nuevo_destino&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;contador&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
                &lt;span class="n"&gt;nuevo_nombre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;contador&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="n"&gt;nuevo_destino&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carpeta_duplicados&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nuevo_nombre&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;shutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;origen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nuevo_destino&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Si algo falla (ej. archivo en uso), simplemente lo ignora
&lt;/span&gt;        &lt;span class="c1"&gt;# para que el script no se detenga.
&lt;/span&gt;        &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Paso 5: Organización
&lt;/h3&gt;

&lt;p&gt;Esta función es la que recorre la carpeta que le pasamos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Lista todo con &lt;code&gt;os.listdir(ruta)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Si es un archivo, busca su extensión en nuestro "mapa" (&lt;code&gt;tipos_de_archivo&lt;/code&gt;) y lo manda a la función &lt;code&gt;mover_archivo&lt;/code&gt;. Si no encuentra la extensión, lo manda a "Otros".&lt;/li&gt;
&lt;li&gt;Si es una carpeta (y no es una de nuestras carpetas de categorías, como "Imagenes"), la mueve toda a una carpeta llamada "Carpetas".
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;organizar_carpeta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tipos&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;archivo&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;archivo_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;archivo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;archivo_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="c1"&gt;# Es un archivo, buscar extensión
&lt;/span&gt;            &lt;span class="n"&gt;extension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;archivo_path&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;categoria&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;extensiones&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tipos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;extensiones&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;destino&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;categoria&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;archivo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="c1"&gt;# Encontramos categoría, rompemos el bucle
&lt;/span&gt;            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# No se encontró, va a "Otros"
&lt;/span&gt;                &lt;span class="n"&gt;destino&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Otros&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;archivo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;mover_archivo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;archivo_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destino&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;archivo_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;archivo&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tipos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="c1"&gt;# Es una carpeta, mover a "Carpetas"
&lt;/span&gt;            &lt;span class="n"&gt;destino&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Carpetas&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;archivo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;mover_archivo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;archivo_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destino&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Paso 6: Ponerlo en marcha
&lt;/h3&gt;

&lt;p&gt;El bloque if &lt;strong&gt;name&lt;/strong&gt;== "&lt;strong&gt;main&lt;/strong&gt;": es lo que realmente ejecuta todo.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Primero, obtiene todas las rutas a organizar de nuestro rutas.txt.&lt;/li&gt;
&lt;li&gt;Luego, hace un bucle for por cada una de esas rutas y llama a organizar_carpeta.&lt;/li&gt;
&lt;li&gt;Al terminar, usa notificar.show_toast() para enviarme una notificación de que se ha completado la ejecución.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# ... (código para encontrar ruta_script y ruta_icon) ...
&lt;/span&gt;
    &lt;span class="c1"&gt;# 1. Obtenemos las rutas del .txt
&lt;/span&gt;    &lt;span class="n"&gt;rutas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;obtener_rutas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta_script&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2. Organizamos cada una
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;rt&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rutas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;organizar_carpeta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tipos_de_archivo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 3. Notificacion
&lt;/span&gt;    &lt;span class="n"&gt;notificar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show_toast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Organizador de archivos&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✅ ¡Archivos de la carpeta descargas organizados!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;icon_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ruta_icon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; En mi caso utilizo &lt;strong&gt;windows&lt;/strong&gt;, por lo que &lt;code&gt;wintoast&lt;/code&gt; me funciona para las notificaciones, si utilizas &lt;strong&gt;linux&lt;/strong&gt;, podrias intentar utilizar otra libreria o herramienta o simplemente saltarte este paso y la importacion de &lt;code&gt;wintoast&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo Usarlo
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Ve a mi repositorio &lt;a href="https://github.com/fiedri/fiedric-toolbox/tree/master/organizador%20de%20archivos" rel="noopener noreferrer"&gt;fiedri's Toolbox&lt;/a&gt; en GitHub.&lt;/li&gt;
&lt;li&gt;Asegúrate de tener Python y las librerías necesarias: pip install wintoast&lt;/li&gt;
&lt;li&gt;Crea una carpeta config al lado del script, y dentro de ella un archivo rutas.txt.&lt;/li&gt;
&lt;li&gt;En rutas.txt, escribe las rutas completas de las carpetas que quieres organizar (ej. C:\Users\fiedri\Downloads), una por línea.&lt;/li&gt;
&lt;li&gt;Ejecútar&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Como automatizar el script (windows)
&lt;/h2&gt;

&lt;p&gt;Para hacer que el script se ejecutara solo, sin tener que hacer nada. La forma más fácil es usar el Programador de Tareas (Task Scheduler).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Busca "Programador de Tareas" en el menú de inicio de Windows.&lt;/li&gt;
&lt;li&gt;En el panel de la derecha, haz clic en "Crear Tarea Básica...".&lt;/li&gt;
&lt;li&gt;Le pones un nombre y eliges cuándo quieres que se ejecute. Yo lo configuré para que corra semanalmente a una hora en la que sé que la PC estará encendida.&lt;/li&gt;
&lt;li&gt;Elige "Iniciar un programa".&lt;/li&gt;
&lt;li&gt;Configuración:

&lt;ul&gt;
&lt;li&gt;En "Programa/script", busca y selecciona tu python.exe (suele estar en C:\Python310\python.exe).&lt;/li&gt;
&lt;li&gt;En "Agregar argumentos", pega la ruta completa al script: C:\ruta\a\tu\organizer_downloads_auto.py.&lt;/li&gt;
&lt;li&gt;Opcional: Si compilaste el script a un .exe (lo que yo hice), solo tienes que poner la ruta a ese .exe en "Programa/script" y listo.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>showdev</category>
      <category>automation</category>
      <category>python</category>
      <category>productivity</category>
    </item>
    <item>
      <title>¿Qué Son los Genéricos?</title>
      <dc:creator>Friedrich Ruiz</dc:creator>
      <pubDate>Sun, 02 Nov 2025 02:02:22 +0000</pubDate>
      <link>https://forem.com/fiedric/notas-conceptuales-que-son-los-genericos-5bdd</link>
      <guid>https://forem.com/fiedric/notas-conceptuales-que-son-los-genericos-5bdd</guid>
      <description>&lt;p&gt;En programacion muchas veces requerimos crear componentes (como funciones, clases o estructuras de datos) que realicen la &lt;strong&gt;misma lógica&lt;/strong&gt; con &lt;strong&gt;diferentes tipos de datos&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Por ejemplo: una funcion que invierte el orden de los elementos en un array. Esta funcion utiliza la misma logica para un &lt;em&gt;array de numeros&lt;/em&gt; que para un &lt;em&gt;array de textos&lt;/em&gt; o un &lt;em&gt;array de objetos&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Si se define la funciona con tipos especificos (ej: number):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;invertir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ... Lógica de inversión&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta función &lt;strong&gt;no puede&lt;/strong&gt; ser reutilizada para &lt;code&gt;Array&amp;lt;string&amp;gt;&lt;/code&gt;. Tendrías que duplicar el código para cada tipo, lo que genera rigidez y mantenimiento complejo.&lt;/p&gt;




&lt;p&gt;Algunos lenguajes, como por ejemplo typescript, permiten el uso de los &lt;em&gt;tipos comodin&lt;/em&gt;, estos serian una solucion. Solo que al utilizar un tipo generico o &lt;code&gt;any&lt;/code&gt;, pierdes la seguridad. El compilador ya no puede verificar si estás llamando a la función correctamente o si estás intentando, por ejemplo, sumar un número con un texto.&lt;/p&gt;




&lt;h2&gt;
  
  
  la mejor solucion:
&lt;/h2&gt;

&lt;p&gt;Los &lt;strong&gt;Genéricos&lt;/strong&gt; son una herramienta de la programación orientada a objetos que resuelve el problema de la rigidez sin sacrificar la seguridad de tipos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Definición
&lt;/h3&gt;

&lt;p&gt;Un genérico es un &lt;strong&gt;marcador de posición de tipo&lt;/strong&gt; (a menudo llamado &lt;strong&gt;&lt;code&gt;T&lt;/code&gt;&lt;/strong&gt; por &lt;em&gt;Type&lt;/em&gt;) que se define al crear un componente (función, clase).&lt;/p&gt;

&lt;p&gt;Esto permite escribir componentes que pueden:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Trabajar con cualquier tipo de dato.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mantener la información del tipo de dato hasta el momento de la ejecución&lt;/strong&gt; (o compilación).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Implementación Conceptual
&lt;/h3&gt;

&lt;p&gt;Al crear un componente, se introduce una "variable de tipo" (el genérico) usando una notación especial (comúnmente los corchetes angulares, &lt;code&gt;&amp;lt; &amp;gt;&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Función GENÉRICA
function invertir&amp;lt;T&amp;gt;(input: Array&amp;lt;T&amp;gt;): Array&amp;lt;T&amp;gt; {
    // La lógica aquí funciona para cualquier tipo T
    // ...
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Uso
&lt;/h3&gt;

&lt;p&gt;Al llamar a la función, el compilador "sustituye" la &lt;code&gt;T&lt;/code&gt; por el tipo real que se está pasando, lo que garantiza la seguridad en toda la ejecución.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Código de Llamada&lt;/th&gt;
&lt;th&gt;El Compilador Entiende&lt;/th&gt;
&lt;th&gt;Seguridad&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;invertir&amp;lt;string&amp;gt;(["a", "b"])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;string&lt;/code&gt; se sustituye por &lt;code&gt;T&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Espera &lt;code&gt;string[]&lt;/code&gt;, devuelve &lt;code&gt;string[]&lt;/code&gt;. ✅ Seguro.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;invertir&amp;lt;number&amp;gt;([1, 2])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;number&lt;/code&gt; se sustituye por &lt;code&gt;T&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Espera &lt;code&gt;number[]&lt;/code&gt;, devuelve &lt;code&gt;number[]&lt;/code&gt;. ✅ Seguro.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;invertir([obj1, obj2])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(El compilador infiere el tipo)&lt;/td&gt;
&lt;td&gt;Determina el tipo de objeto. ✅ Seguro.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  En Resumen: El Valor de los Genéricos
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Característica&lt;/th&gt;
&lt;th&gt;Propósito&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reutilización&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Escribir la lógica una sola vez para múltiples tipos.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Seguridad de Tipos&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;El compilador garantiza que los tipos de entrada y salida coincidan.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flexibilidad&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;El componente no se compromete con un tipo específico hasta que es utilizado.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>typescript</category>
      <category>notasconceptuales</category>
    </item>
  </channel>
</rss>
