2

I have a repertory where some of the files have to be renamed :

alabama.txt   california1.txt   california2.txt   california3.txt   florida.txt

The californiaX.txt files should be renamed cX.txt, X being a number.

Here is what I tried :

ls | sed 's/california/c/' 

but this cannot store the results. Reading some other posts, I tried adding sh but it says "command not found".

ls | sed 's/california/c/' | sh

The rename command doesn't work either (I'm on Mac). The mv command works only for a file. So I tried a loop, which, same, doesn't work :

for file in california*; do  mv file c*; done

Any info on what I'm doing wrong would be welcome.

Natha
  • 364
  • 1
  • 3
  • 20
  • 1
    It's dangerous to randomly type commands on the terminal without fully understand what they do! for example `ls | ... | sh` is, well, potentially harmful! – gniourf_gniourf Dec 29 '16 at 21:04
  • What do you mean by harmful ? I found this [here] (http://stackoverflow.com/questions/2372719/using-sed-to-mass-rename-files) – Natha Dec 29 '16 at 21:20
  • 1
    Don't trust the internet! I mean that you're potentially executing arbitrary commands... you could have executed commands that would have wiped your home directory. Your link shows some rather bad practice! it's not because it's on SO and has high votes that it is good. – gniourf_gniourf Dec 29 '16 at 21:36
  • 1
    It's horrifying to realize that anybody can randomly copy and paste code without understanding what its meaning is... – gniourf_gniourf Dec 29 '16 at 21:39
  • It's horrifying to realize that anybody can randomly criticize people that are actually learning, which by definition means making lots of mistakes and trying different options, instead of explaining why some trials are bad option. – Natha Dec 29 '16 at 21:56
  • I wasn't targeting you at all when writing that. Rather targeting the whole QA system, that sometimes contains horrendous answers. – gniourf_gniourf Dec 29 '16 at 21:59
  • 1
    Now if you want to know what's bad about your strategy that consists of piping _data_ through `sh`: in _a new empty directory,_ create a file named `californialear` and run your command: `ls | sed 's/california/c/' | sh`. Congratulations, you just executed the command `clear`. I could have executed any other command like so, even potentially dangerous ones! Piping through a shell is as bad using `eval`. Did you learn something? – gniourf_gniourf Dec 29 '16 at 22:04
  • Ok thanks I understood what it does and what's the risk, but I still don't really get what exactly does the `sh` command. And anyhow, is there a way to achieve renaming files without a for loop ? – Natha Dec 29 '16 at 22:26
  • 1
    The `| sh` just feeds everything _for execution by the shell `sh`!_ To rename your files, use a `for` loop like shown in the answers here. It's really the idiomatic way! – gniourf_gniourf Dec 29 '16 at 22:28

3 Answers3

3

A variable, when referred should be led with a $ (when declared, it is not). And, you should make parameter substition into "file" variable:

for file in california*; do mv "$file" "${file/california/c}"; done
Serhat Cevikel
  • 720
  • 3
  • 11
1

Use mv with bash substring-extraction as

for file in california*.txt
do
    mv -v -- "$file" "${file:0:1}${file:10:1}.${file#*.}"
done

Here, -- is a bash built-in to signify the end of command options, after which only positional parameters are accepted and no more command flags. And the sub-string extraction part is

${string:position} and ${string:position:length}

"string" specifies our variable name and the "position" is our starting point to extract information from. We can fine tune this further by using the "length" parameter. When length is used with position this means display information starting at position x for a length of y.

Community
  • 1
  • 1
Inian
  • 80,270
  • 14
  • 142
  • 161
1

To rename a file, you need: 1. the old name, 2. the new name.

Your attempts either get the old name or the new name. None try to find both at the same time.

Here are your attempts put together into a working solution:

for file in california*
do
  newname=$(echo "$file" | sed 's/california/c/')
  mv "$file" "$newname"
done

This can more canonically be written inlined with parameter expansion:

for file in california*
do
  mv "$file" "c${file#california}"
done
that other guy
  • 116,971
  • 11
  • 170
  • 194