2

I have Python script which reads files names from oldFiles.txt, iterate through files names which are files in a Linux directory, then update the files names using string.replace and finally run a subprocess to find those files (let's say in home directory to make the explanation and demo easier) and change their names using

subprocess.run(['mv', 'oldfile', 'newfile')]

Let's suppose I have files names with string "jane" and I want to replace it with "jdoe", a file's name example would be: abcd_jane.csv modified into abcd_jdoe.csv

The sys.argv[1] is the argument which will be passed like the follow

./changeJane.py oldFiles.txt

I am using those empty files for local training, their names are saved in oldFiles.txt

sdafsdfs_jane.doc 12fgdf-jane.csv files_jane.txt

Iterating and updating files names in oldFiles.txt is ok or maybe there is some mistakes also :-( but I still couldn't figure out how to run the subprocess to achieve my goal like described above. This is what I came in, thank you very much.

PS: I am forced to use sys and subprocess modules, and also forced to apply all the mentioned details, its a homework assessment.

#!/usr/bin/env python3
import sys
import subprocess
with open(sys.argv[1], 'r+') as f:
  for line in f.readlines():
    newline = line.strip()
    newtext = newline.replace("jane", "jdoe")
    subprocess.run(['mv', '~/newline', '~/newtext']) #I know its wrong but this is my limit!

UPDATE

I modified the script to return list and comfortably iterate through its items, the script is successful but it is doing one iteration only which means it is applying only the first file name or the first iteration, any ideas to do all the iterations and finish the job. Thank you very much!!

#!/usr/bin/env python3
import sys
import subprocess
with open(sys.argv[1], 'r') as f:
    content1 = f.readlines()
    content2 = [x.strip() for x in content1]
    content3 = [item.replace("jane", "jdoe") for item in content2]
    for x in content2:
      for i in content3:
        subprocess.run(['mv', '/home/ninja-coder/'+x, '/home/ninja-coder/'+i])
  • 2
    You are overthinking the solution. Forget about `subprocess` and take a look at `os.rename`. – Poshi Jul 10 '20 at 22:04
  • Hi Poshi. In fact I am forced to use sys and subprocess modules, its a homework assessment. –  Jul 10 '20 at 22:07
  • Please upvote if you find my question relevant. Thanks. –  Oct 22 '20 at 21:50

7 Answers7

2

Your first code is simpler and you are almost right! The reason that you don't get the required output in the first code is because you haven't added the full path to mv command

#!/usr/bin/env python3
import sys
import subprocess
f= open (sys.argv[1],"r")
path='/home/<username>'
for line in f.readlines():
 old_name = line.strip()
 new_name = old_name.replace("jane","jdoe")
 subprocess.run(["mv",path+old_name,path+new_name])
f.close()

This worked for me!

dread_user
  • 21
  • 3
1

Thanks to @Jonatã and @HackLab for their hints. After several trials I solved this very annoying assessment but I learned lots of things, again, one of the crucial success's secrets is PRACTICE, here is the final code

#!/usr/bin/env python3
import sys
import subprocess
with open(sys.argv[1], 'r') as f:
    content1 = f.readlines()
    content2 = [x.strip() for x in content1]
    content3 = [item.replace("jane", "jdoe") for item in content2]
    res = dict(zip(content2, content3))
    for key, value in res.items():
        subprocess.run(['mv', '/home/ninja-coder/'+key, '/home/ninja-coder/'+value])
1

Using nested loops is not a good practice here and would not work for the purpose. It is easier to use zip than dictionaries

import sys
import subprocess

from pathlib import Path
with open (sys.argv[1], "r") as f:
    data=[ x.strip() for x in  f.readlines()]
    datanew=[x.replace("jane","jdoe") for x in data]
    for k, t in zip( data,datanew):
      subprocess.run(["mv",'<add path>'+k,'<add path>/+t'])
f.close()
Haris
  • 130
  • 7
0

Using a subprocess to rename a file is too costly and too much work for you. Rename the file with the tools that Python itself offers to you. Also, you don't need to open the file for writing and you can iterate over the file just refering to the file:

#!/usr/bin/env python3

import sys
import subprocess

with open(sys.argv[1], 'r') as f:
  for line in f:
    newline = line.strip()
    newtext = newline.replace("jane", "jdoe")
    os.rename(newline, newtext)
Poshi
  • 5,332
  • 3
  • 15
  • 32
0

I am not sure why you want to open a file if you want to change the filename. I think you want to iterate over all files in a directory for that you need os.listdir() https://www.tutorialspoint.com/python/os_listdir.html

import os

path = "./"

for filename in os.listdir(path):
    newFilename = filename.replace("jane", "jdoe")
    os.rename(path + filename, path + newFilename)

as @Poshi pointed out no need for subprocess os.rename should do it https://www.tutorialspoint.com/python/os_rename.htm

If you really want to use subprocess

subprocess.run(['mv', path + filename, path + newFilename])

UPDATE

Here now the complete solution I hope that makes it clearer.

#!/usr/bin/env python3
import sys
import subprocess
with open(sys.argv[1], 'r') as f:
    for filename in f.readlines():
        newFilename = filename[:-1].strip().replace("jane", "jdoe")
        subprocess.run(['mv', "~/" + filename[:-1], "~/" + newFilename])
HackLab
  • 509
  • 3
  • 10
  • `subprocess.run(['mv', path + filename, path + newFilename])` but I don't know why Linux is not accepting variables names as path like `~/newline` which equals to a file name in oldFiles.txt and already exist in Linux directory. –  Jul 10 '20 at 22:18
  • here is the output of your script bro `mv: cannot stat '~/sdafsdfs_jane.doc'$'\n': No such file or directory` while the name of the file is correct and the files is there but I don't know why it is not passing. Please excuse me for bothering you. I appreciate so much your very precious help. –  Jul 10 '20 at 22:34
  • can you provide an example of the oldFiles.txt – HackLab Jul 10 '20 at 22:37
  • I am using those empty files for local training, they are saved in oldFiles.txt `sdafsdfs_jane.doc 12fgdf-jane.csv files_jane.txt` –  Jul 10 '20 at 22:40
  • Found the problem in the file there is of course linebreak at the end represented with \n this needs to stripped away – HackLab Jul 10 '20 at 22:50
  • The files names are saved one file's name per line not all in the same line as showed in the previous commentary. Thank you very much. –  Jul 10 '20 at 22:50
  • names already stripped before replacing the string so I do not understand where it comes from?? I don't know how to solve it, I 've been one week now fighting this very annoying subprocess –  Jul 10 '20 at 22:59
  • should I add this line `tr -d '\n'` ?? –  Jul 10 '20 at 23:02
  • I already update my update `filename[:-1]` strips the last char of the filename `.strip()` does not strip linebreaks it seems. Alternativly you can try `.strip('\n')` – HackLab Jul 10 '20 at 23:06
  • even so `mv: cannot stat '~/sdafsdfs_jane.doc 12fgdf-jane.csv files_jane.txt ': No such file or directory` I wanna get drunk now loool this assessment is such stubborn. Could be stdout bug ? –  Jul 10 '20 at 23:08
0
#!/usr/bin/env python3

import sys
import subprocess
impotr os

with open(sys.argv[1], 'r') as f:
    for line in f:
        newline = line.strip()
        newtext = newline.replace("jane", "jdoe")
        os.rename(newline, newtext)
RiveN
  • 2,595
  • 11
  • 13
  • 26
0
`
#!/usr/bin/env python3

import sys
import subprocess

with open(sys.argv[1],'r') as f:
        path='/home/student-01-88c93c037e85'
        for filename in f.readlines():
                filename = filename.strip()
                newname = filename.rstrip().replace("jane","jdoe")
                subprocess.run(["mv",path+filename,path+newname])
        f.close()

`
  
  • Welcome to SO! Please don't post code-only answers but add a little textual explanation about how and why your approach works and what makes it different from the other answers given. You can find out more at our ["How to write a good answer"](https://stackoverflow.com/help/how-to-answer) page. – ahuemmer Dec 22 '22 at 10:22