<?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>DEV Community: Alex Delgado</title>
    <description>The latest articles on DEV Community by Alex Delgado (@adelgado).</description>
    <link>https://dev.to/adelgado</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%2F517862%2Fca1cc281-e217-4f8d-8a90-1fc9bd418d53.jpg</url>
      <title>DEV Community: Alex Delgado</title>
      <link>https://dev.to/adelgado</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adelgado"/>
    <language>en</language>
    <item>
      <title>Uso practico de bash: Ejecutar un comando sobre varios archivos</title>
      <dc:creator>Alex Delgado</dc:creator>
      <pubDate>Wed, 06 Jul 2022 18:24:35 +0000</pubDate>
      <link>https://dev.to/adelgado/uso-practico-de-bash-ejecutar-un-comando-sobre-varios-archivos-3o0h</link>
      <guid>https://dev.to/adelgado/uso-practico-de-bash-ejecutar-un-comando-sobre-varios-archivos-3o0h</guid>
      <description>&lt;p&gt;Existen ocasiones en los que es necesario aplicar una serie de comandos en diferentes archivos, lo cual seria muy tedioso realizar manualmente, pero se puede lograr fácilmente con un poco de scripting en bash.&lt;/p&gt;

&lt;p&gt;Vamos a empezar dando un ejemplo practico, tenemos un proyecto con la siguiente estructura:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── Dockerfile
├── LICENSE
├── MANIFEST.in
├── README.md
├── VERSION
├── flake8.ini
├── mypy.ini
├── requirements_dev.txt
├── requirements_pkg.txt
├── setup.py
├── src
│   └── bodywork
│       ├── __init__.py
│       ├── cli
│       │   ├── __init__.py
│       │   ├── cli.py
│       │   ├── deployments.py
│       │   ├── secrets.py
│       │   ├── setup_namespace.py
│       │   ├── terminal.py
│       │   └── workflow_jobs.py
│       ├── config.py
│       ├── constants.py
│       ├── exceptions.py
│       ├── git.py
│       ├── k8s
│       │   ├── __init__.py
│       │   ├── auth.py
│       │   ├── batch_jobs.py
│       │   ├── deployments.py
│       │   ├── namespaces.py
│       │   ├── pod_logs.py
│       │   ├── secrets.py
│       │   ├── utils.py
│       │   └── workflow_jobs.py
│       ├── logs.py
│       ├── stage_execution.py
│       └── workflow_execution.py
├── structure.txt
├── tests
│   ├── conftest.py
│   ├── integration
│   │   ├── conftest.py
│   │   ├── test_git_integration.py
│   │   ├── test_k8s_with_cluster.py
│   │   └── test_k8s_with_secrets.py
│   ├── resources
│   │   └── project_repo
│   │       ├── bodywork.ini
│   │       ├── bodywork.yaml
│   │       ├── bodywork_bad_stages_section.yaml
│   │       ├── bodywork_batch_stage.yaml
│   │       ├── bodywork_empty.yaml
│   │       ├── bodywork_missing_sections.yaml
│   │       ├── on_fail_stage
│   │       │   └── main.py
│   │       ├── stage_1
│   │       │   └── main.py
│   │       ├── stage_2
│   │       │   └── main.py
│   │       ├── stage_3
│   │       │   └── main.py
│   │       ├── stage_4
│   │       │   └── main.py
│   │       ├── stage_5
│   │       │   └── main.py
│   │       └── stage_jupyter
│   │           └── main.ipynb
│   └── unit_and_functional
│       ├── conftest.py
│       ├── test_cli.py
│       ├── test_cli_deployments.py
│       ├── test_cli_secrets.py
│       ├── test_cli_setup_namespace.py
│       ├── test_cli_terminal.py
│       ├── test_cli_workflow_jobs.py
│       ├── test_config.py
│       ├── test_git.py
│       ├── test_k8s_auth.py
│       ├── test_k8s_batch_jobs.py
│       ├── test_k8s_deployments.py
│       ├── test_k8s_namespaces.py
│       ├── test_k8s_pod_logs.py
│       ├── test_k8s_secrets.py
│       ├── test_k8s_utils.py
│       ├── test_k8s_workflow_jobs.py
│       ├── test_logs.py
│       ├── test_stage_execution.py
│       └── test_workflow_execution.py
├── tox.ini
└── xclip

16 directories, 75 files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nuestra tarea es cambiar todos los &lt;a href="%5Bhttps://peps.python.org/pep-0257/%5D(https://peps.python.org/pep-0257/)"&gt;Docstrings&lt;/a&gt; dentro de los archivos python, a &lt;a href="%5Bhttps://google.github.io/styleguide/pyguide.html%5D(https://google.github.io/styleguide/pyguide.html)"&gt;Formato Google&lt;/a&gt;, esto podría llevarnos horas y es propenso a errores, ya que es probable que ni siquiera conozcamos todas las diferencias entre ambos formatos.&lt;/p&gt;

&lt;p&gt;Para ello después de un poco de investigación, encontramos en github el paquete &lt;a href="%5Bhttps://github.com/dadadel/pyment%5D(https://github.com/dadadel/pyment)"&gt;Pyment&lt;/a&gt;, el cual resuelve el problema de tener que modificar los archivos de manera manual, sin embargo, si leemos en la documentación, podemos encontrar que para realizar esta tarea se requieren una serie de comandos sobre cada archivo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Generar el archivo patch&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;pyment test.py

&lt;span class="c"&gt;# Aplicar patch al archivo original&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;patch &lt;span class="nt"&gt;-p1&lt;/span&gt; test.py.patch

&lt;span class="c"&gt;# Borrar archivo patch&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;rm &lt;/span&gt;test.py.patch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si bien la cantidad de trabajo disminuye considerablemente, todavía es necesario encontrar cada archivo y ejecutar estos comandos, lo cual sigue consumiendo bastante tiempo ( sin mencionar lo tedioso que puede ser)&lt;/p&gt;

&lt;p&gt;Para hacer esto aun mas sencillo, usaremos el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s1"&gt;'*.py'&lt;/span&gt; | xargs  &lt;span class="nt"&gt;-I&lt;/span&gt; % bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'cd $(dirname %) ; pyment $(basename %); patch -p1 &amp;lt; $(basename %).patc
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dividamos este comando en varias para explicarlo mas fácilmente, primero que nada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s1"&gt;'*.py'&lt;/span&gt;
./setup.py
./src/bodywork/workflow_execution.py
./src/bodywork/__init__.py
./src/bodywork/config.py
./src/bodywork/logs.py
./src/bodywork/exceptions.py
./src/bodywork/constants.py
./src/bodywork/k8s/utils.py
./src/bodywork/k8s/pod_logs.py
./src/bodywork/k8s/deployments.py
./src/bodywork/k8s/__init__.py
./src/bodywork/k8s/batch_jobs.py
./src/bodywork/k8s/workflow_jobs.py
./src/bodywork/k8s/namespaces.py
./src/bodywork/k8s/secrets.py
./src/bodywork/k8s/auth.py
./src/bodywork/cli/cli.py
./src/bodywork/cli/deployments.py
./src/bodywork/cli/__init__.py
./src/bodywork/cli/setup_namespace.py
./src/bodywork/cli/terminal.py
./src/bodywork/cli/workflow_jobs.py
./src/bodywork/cli/secrets.py
./src/bodywork/stage_execution.py
./src/bodywork/git.py
./tests/unit_and_functional/test_k8s_batch_jobs.py
./tests/unit_and_functional/test_k8s_auth.py
./tests/unit_and_functional/test_cli_secrets.py
./tests/unit_and_functional/test_k8s_utils.py
./tests/unit_and_functional/test_cli_workflow_jobs.py
./tests/unit_and_functional/test_cli_setup_namespace.py
./tests/unit_and_functional/test_k8s_deployments.py
./tests/unit_and_functional/test_k8s_namespaces.py
./tests/unit_and_functional/test_k8s_pod_logs.py
./tests/unit_and_functional/test_cli_deployments.py
./tests/unit_and_functional/test_workflow_execution.py
./tests/unit_and_functional/test_cli_terminal.py
./tests/unit_and_functional/test_stage_execution.py
./tests/unit_and_functional/test_k8s_secrets.py
./tests/unit_and_functional/test_k8s_workflow_jobs.py
./tests/unit_and_functional/conftest.py
./tests/unit_and_functional/test_logs.py
./tests/unit_and_functional/test_config.py
./tests/unit_and_functional/test_cli.py
./tests/unit_and_functional/test_git.py
./tests/resources/project_repo/stage_3/main.py
./tests/resources/project_repo/stage_2/main.py
./tests/resources/project_repo/stage_4/main.py
./tests/resources/project_repo/stage_1/main.py
./tests/resources/project_repo/on_fail_stage/main.py
./tests/resources/project_repo/stage_5/main.py
./tests/integration/test_git_integration.py
./tests/integration/test_k8s_with_cluster.py
./tests/integration/conftest.py
./tests/integration/test_k8s_with_secrets.py
./tests/conftest.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;El comando find regresa una lista de archivos que cumplan con los parámetros de búsqueda especificado&lt;/li&gt;
&lt;li&gt;Este comando require especificar el directorio a partir del cual se buscaran archivos, utilizamos &lt;code&gt;.&lt;/code&gt; que es un alias para el directorio actual&lt;/li&gt;
&lt;li&gt;La bandera &lt;code&gt;-name '*.py'&lt;/code&gt;  indica nuestro parámetro de búsqueda, que en este caso seran todos los archivos con terminación .py&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Utilizaremos el operador pipe, que permite ingresar la salida de un comando como la entrada de un comando posterior, pasando asi nuestra lista de archivos al comando &lt;code&gt;xargs&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ $ &lt;/span&gt;xargs  &lt;span class="nt"&gt;-I&lt;/span&gt; % bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'cd $(dirname %) ; pyment $(basename %); patch -p1 &amp;lt; $(basename %).patc
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;El comando xargs nos permite ejecutar un comando a cada uno de los elementos de una lista, en este caso, nos permite ejecutar un comando a cada uno de los archivos resultantes del comando anterior&lt;/li&gt;
&lt;li&gt;La bandera &lt;code&gt;-I %&lt;/code&gt; Nos permite especificar un símbolo que sera utilizado como placeholder dentro del comando para representar el nombre del archivo.&lt;/li&gt;
&lt;li&gt;Los argumentos siguientes  &lt;code&gt;bash -c 'cd $(dirname %) ; pyment $(basename %); patch -p1 &amp;lt; $(basename %).patch; rm $(basename %).patch&lt;/code&gt;  especifican el comando que sera utilizado en cada iteración:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Cambiar al directorio del archivo&lt;/span&gt;
&lt;span class="c"&gt;# Recordemos que el comando find nos devuele resultados de la siguiente manera&lt;/span&gt;
&lt;span class="c"&gt;# ./src/bodywork/workflow_execution.py&lt;/span&gt;
&lt;span class="c"&gt;# El comando dirname nos regresa el directorio de un archivo, removiendo&lt;/span&gt;
&lt;span class="c"&gt;# el placeholder esto sera equivalente a &lt;/span&gt;
&lt;span class="c"&gt;# cd $(dirname ./src/bodywork/workflow_execution.py);&lt;/span&gt;
&lt;span class="c"&gt;# cd ./src/bodywork/&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; %&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c"&gt;# Una vez dentro del directorio ejecutamos el comando pyment sobre el archivo&lt;/span&gt;
&lt;span class="c"&gt;# De igual manera, el comando basename regresa el nombre de un archivo,&lt;/span&gt;
&lt;span class="c"&gt;# Sustituyendo el placeholder esto sera equivalente a&lt;/span&gt;
&lt;span class="c"&gt;# pyment $(basename ./src/bodywork/workflow_execution.py);&lt;/span&gt;
&lt;span class="c"&gt;# pyment workflow_execution.py&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;pyment &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; %&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c"&gt;# Aplicar patch&lt;/span&gt;
&lt;span class="c"&gt;# Sustituyendo el placeholder esto sera equivalente a&lt;/span&gt;
&lt;span class="c"&gt;# $ patch -p1 &amp;lt; $(basename /src/bodywork/workflow_execution.py).patch'&lt;/span&gt;
&lt;span class="c"&gt;# $ patch -p1 &amp;lt; workflow_execution.py.patch&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;patch &lt;span class="nt"&gt;-p1&lt;/span&gt; &amp;lt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; %&lt;span class="si"&gt;)&lt;/span&gt;.patch&lt;span class="s1"&gt;'

# Eliminar Archivo patch generado
$ rm $(basename %).patch

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

&lt;/div&gt;



</description>
      <category>spanish</category>
    </item>
  </channel>
</rss>
