How to recursively rename numbered files by naming other files

Asked

Viewed 861 times

2

What I am currently looking to do is rename all files in a folder, where there are also other files of different format. See Example:

FOLDER - BEFORE

1.txt 2.txt 3.txt 

Daniela.jpg Amanda.jpg Lucia.jpg

What I’m not getting is exactly creating a bond for commanding sed and/or mv so that, I can achieve the goal.

FOLDER - AFTER

Daniela.txt Amanda.txt Lucia.txt 

Daniela.jpg Amanda.jpg Lucia.jpg

Even if it seems strange to those who read, keep in mind that I want copy the names remaining the extension.

Example of what I tried:

cd /home/$USER/pasta/

QUANTIDADE=`ls *.jpg | wc -l`     

LISTA=`ls *.txt`
for ARQUIVO in `seq $QUANTIDADE`
do 
  mv "$ARQUIVO" "$LISTA"
done

cd ..

Instructions - For those who wish to have an idea formulated in the mind of what is necessary to help the question. I make it clear here a step-by-step so that you can recreate my desktop environment on your MAC system; Minix; Openbsd; Freebsd or GNU/Linux. Let us know:

1 - Create a directory named "folder" in your home directory /home/user:

$ mkdir pasta

2 - Populate the previously created folder with dummy files:

$ touch 1.txt 2.txt 3.txt /home/$USER/pasta/

$ touch Daniela.jpg Amanda.jpg Lucia.jpg /home/$USER/pasta/

3 - Finally, copy the example script. Give common execution permission:

$ sudo chmod +x <script.sh> 

Now, just run the tests to see what comes.


I have no command rename in my system so please anyone who wants to help me by answering the question, do not elaborate with this tool.

Another detail is that, I prefer to use syntax that rotates in Bourne shell instead of Bash. Nothing against, it’s only for portability.

  • I don’t understand your doubt, you want to change the name of all files regardless of format? Or you want to rename a particular file type based on another file type?

  • We have a problem, all 01 will be renamed Daniela, 02 to Amanda and 03 to Lucia? If not, first we have to have a DE-PARA stating that such a filename will go to another filename. We have to have a filename pattern.

  • @Alessandroschneider You understood yes! That’s exactly what you said in your comment - [...]rename a particular file type based on another file type.

3 answers

2

Due to the issue of portability, I decided to bring this script as part of the solution. Noting that, the response of dear colleague Alessandro Schneider was given the height. However, it only has support for the Mr. Bash, in what the statement array[there is no Bourne shell]. So I decided to fight a little more in order to elaborate something that would also fulfill the task and not use vetores.

See solution:

Bourn Shell

#!/bin/sh

cd /home/$USER/pasta

qtd=$(ls *.jpg | wc -l)

ext1=$(ls -1 *.txt)

ext2=$(ls -1 *.jpg)

num=0
while [ $num -lt $qtd ]
do 
  for j in $ext1
   do
     for p in $ext2
      do
        mv $num.${j##*.} ${p%.*}.txt
        num=$[num + 1]
    done
  done
done

cd ..

Explanation

1 - We define the Shebang for Bourne Shell for being commonly used and distributed on various GNU/Linux systems.

#!/bin/sh   

2 - We enter the folder containing the files to be renamed.

cd /home/$USER/pasta

3 - qtd - that is to say amount maximum of JPG files in which we will make use of their name in order to rename the other TXT files.

qtd=$(ls *.jpg | wc -l)

4 - List TXT files

ext1=$(ls -1 *.txt)

5 - List JPG files

ext2=$(ls -1 *.jpg)

6 - num- that is to say number count start at 0

num=0

7 - While[While] - is used to repeat as far as we determine, in my code will quantify to the maximum number of file '*. jpg'. So while $num is less than $qtd continue, or stop!

while [ $num -lt $qtd ]     

8 - The first and second for in turn, does the job of interlink the two variables stipulated at the beginning. Where are renamed file-to-file, with the name declared by the position.

  for j in $ext1
    do
    for p in $ext2
        do

Obs.: Here comes the process of naming the *.txt files to the *.jpg filename. Notice that between loop lines for we have:

    mv $num.${j##*.} ${p%.*}.txt    

Note - the command mv followed by Expansion of the Shell Parameter:

  • We want to capture only the extension afterward of "."

    ${j##.}
    
  • We want to capture only the string before of "."

    ${p%.*}
    

9 - At this point, let’s go increase always for the next file and/or file number to be processed.

       num=$[num + 1]           

10 - Not wanting to view the output result in terminal[console], we use:

done &>/dev/null    

.. the front of "done".

Finally, we leave the workbook and return a point above to the previous directory

cd ..


Important! - This script, is in its perfect functioning only with ordinal numbers: 1 2 3 4 5 6 7 8 9 10 11 12 etc ...

Not being able to operate with due role on numbers that accompanies in its tenth, twentieth, thirtieth position and so on, the number "0". See:

00 01 02 03 04 05 06 07 08 09 .. 020 021 .. 034 035 ... and so on.

2


If I understand correctly you want to rename all the files txt with the filenames jpg, in the example below I considered that it has the same amount of files of both formats.

#!/bin/bash
# Pega o diretório onde deseja fazer a ação
Dir=$(pwd)
# Lista todos os arquivos do tipo txt
files=$(ls -1 $Dir | grep .txt)
# Lista todos os arquivos do tipo jpg
rename=$(ls -1 $Dir | grep .jpg | cut -d. -f1)
# Declara o array
array=($(echo $rename))
# Posição do array
po=0
# faz o for renomeado arquivo por arquivo, com o nome declarado na possição do array
for i in $files; do
    mv $i ${array[$po]}.txt
    ## Adiciona mais um para alterar a possição do array
    po=$[po + 1]
done

I see several ways to reach your goal, that was the simplest.

0

You can’t associate 1.txt with Daniela.jpg, 2.txt with Amanda.jpg and 3.txt with Lucia.jpg, because the files will be listed in alphabetical order.

I believe the user needs (or wants) a description file .txt referent to photographs .jpg, so that, reading the Amanda.txt, the text describes what is seen or will be seen in the photo Amanda.jpg, like, a synopsis of a movie poster. It’s much easier that way:

  1. Before writing the 'synopsis' on the photo, create the files .txt;
  2. Open a terminal in the directory/folder where the files are .jpg (can have 3 or 300 files) and run the script below a line.
for arqv in `ls *.jpg | cut -d. -f1`; do touch $arqv.txt; done

For each .jpg, a .txt. Now the user edits the .txt placing the corresponding content.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.