I have two subdirectories, s1
and s2
, and each has files named file_1
and file_2
in them. How do I change the names of these files into, let's say, s1_file1
, s1_file2
, and s2_file1
, s2_file2
, such that we know what they are representing?

- 333,661
-
1Should the solution also detect the files that have the same names so that, if there are other files that are named the same, these should be renamed too, while all other files are left as they are? How should name collisions be handled (i.e., the case where the new name of a file is already taken)? Will you always have two subdirectories and never one, three or more? – Kusalananda Apr 18 '22 at 06:28
-
Suggestion: Read and learn from this question, and its answers. You can probably adapt the answers there to your situation. – Seamus Apr 19 '22 at 00:57
-
The prefix S1 could be added to all the files in the subdirectory and as far as name collisions go they wont be a problem and I might have more than two subdirectories – user17273899 Apr 19 '22 at 13:20
-
Ah - OK... I suppose the alternative is to just lie there and wallow about. Seems a shame though... an investment in a proper question could get you the best free help you'll find in the world in this SE. Unlike everything else today, the cost of an answer here remains the same as it has been since it was founded. – Seamus Apr 20 '22 at 21:58
-
well I guess nothing comes free in this SE, even an unhelpful answer as yours comes with a dose of distasteful sarcasm – user17273899 Apr 21 '22 at 22:10
2 Answers
Your question omits details that might lead to a more general answer. This answer may not be generally useful, but it answers your question as stated.
Use mv
:
$ mkdir s1 s2
$ touch s1/file_1 s1/file_2 s2/file_1 s2/file_2
$ mv s1/file_1 s1/s1_file_1
$ mv s1/file_2 s1/s1_file_2
$ mv s2/file_1 s2/s2_file_1
$ mv s2/file_2 s2/s2_file_2
$ ls -l s1 s2
s1:
total 0
-rw-r--r-- 1 pi pi 0 Apr 18 00:14 s1_file_1
-rw-r--r-- 1 pi pi 0 Apr 18 00:14 s1_file_2
s2:
total 0
-rw-r--r-- 1 pi pi 0 Apr 18 00:14 s2_file_1
-rw-r--r-- 1 pi pi 0 Apr 18 00:14 s2_file_2

- 2,925
-
:) A downvote for... lack of clairvoyance? It answers the question asked, no? – Seamus Apr 18 '22 at 06:48
With zsh
(and GNU mv
for its -T
option), renaming the (non hidden) files that are found with the same name (same t
ail) in more than one (non hidden) subdirectory (leaving the unique ones alone):
typeset -A count
subdirs=(*(N/))
files=($^subdirs/*(N))
for f ($files) (( ++count[\$f:t] ))
for f ($files) if (( count[\$f:t] > 1 )) mv -Ti -- $f $f:h/${f:h}_$f:t
(note that we don't do files=(*/*(N))
to avoid considerings files in symlinks to directories).
Note that after running that, you may still end up with files with the same names, like for instance if there were s1/file
, s1/s2_file
and s2/file
files beforehand.
To get a report of which file names are duplicated before doing the renaming, you can run (with the extendedglob
option enabled):
print -raC2 -- ${(kv)count[(R)^1]}
Which print
s r
aw on 2
C
olumns (a
cross) the k
eys and v
alues of the count
A
ssociative array for which the value is not (^
) 1
(using R
everse subscripting).
To consider only regular files (to the exclusion of any other type of files such as fifos, directories, sockets, devices...), add the .
glob qualifier (files=($^subdirs/*(N.))
). To also consider hidden files or files in hidden subdirs, you can add the D
glob qualifier, but note that if you add a prefix that doesn't start with a dot, the file will no longer be hidden.

- 544,893