在Linux中重命名文件

huangapple go评论112阅读模式
英文:

renaming files in linux

问题

我有以下文件格式:

schema_tableName_1.sql
schema_tableName_2.sql
schema_tableName_3.sql
...

如何将这些文件重命名,使格式如下:

tableName_1.sql
tableName_2.sql
tableName_3.sql
...

文件应该保留在相同的目录中。我尝试了:

mv "*schema_tableName*" tableName_*
英文:

I have files in format:

schema_tableName_1.sql
schema_tableName_2.sql
schema_tableName_3.sql
...

How can I rename the files so that the format looks like this:

tableName_1.sql
tableName_2.sql
tableName_3.sql
...

The files should stay in the same directory. I tried:

mv "*schema_tableName*"  tableName_*

答案1

得分: 1

我尝试了:

mv "*schema_tableName*"  tableName_*

这样的做法肯定行不通。

首先,请注意"*schema_tableName*"周围的引号会抑制其内容的路径名展开。也就是说,它们会将星号(*)视为普通字符。一般来说,解释模式的责任在于Shell,而不是由其执行的命令,因此将这样的文件名传递给mv对你没有任何有用的作用。

其次,如果各种目标文件尚不存在,那么tableName_*会根据Shell选项的当前值展开为它本身或为空,具体取决于当前的Shell选项,但这两种情况都对你没有用。

第三,假设你实际上有如下命令:

mv schema_tableName_1.sql schema_tableName_2.sql schema_tableName_3.sql \
          tableName_1.sql        tableName_2.sql        tableName_3.sql

或者

mv schema_tableName_1.sql tableName_1.sql \
   schema_tableName_2.sql tableName_2.sql \
   schema_tableName_3.sql tableName_3.sql

或者展开为其中之一。看起来你可能想要这样的效果,但mv对这些情况不起作用。除非只给它提供一个非选项参数的单一对文件名,否则它不会执行成对的移动操作。当向它提供多于两个非选项参数时,最后一个参数必须是一个目录,而其他所有参数命名的文件都将移动到该目录下。

要执行成对的移动操作,你需要为每一对使用一个mv命令。这时Shell的for循环是一个自然的选择。而且你需要想办法从源文件名生成目标文件名。Shell具有适用于此的参数展开选项。总之:

for f in schema_tableName_*.sql; do
  mv "${f}" "${f#schema_}"
done

这会展开schema_tableName_*.sql的通配符,然后针对每个结果文件名依次设置Shell变量f为该文件名,并执行dodone之间的命令。"${f#schema_}"会将变量f的值去掉前缀"schema_"(如果存在)。这样你就得到了你想要的成对mv命令。

此外,由于你标记了Linux,你可以考虑使用rename命令。它可以基于字符串替换执行多个文件重命名操作,因此命令可能会稍微简单一些,但它是特定于Linux的:

rename schema_ '' schema_tableName_*.sql

我通常建议优先使用标准命令,如mv,而不是特定于平台的命令,如rename,因为这样可以培养更广泛可重用的技能(例如在MacOS中也可以使用),但具体情况可能有所不同。

英文:

> I tried:
>
> mv "*schema_tableName*" tableName_*
>

Nothing along those lines can possibly work.

In the first place, note that the quotation marks around "*schema_tableName*" suppress pathname expansion of their contents. That is, they cause the asterisks (*) to be treated as ordinary characters. Generally speaking, it is the shell, not commands executed by it, that is responsible for interpreting patterns, so passing such filenames through to mv does nothing useful for you.

In the second place, if the various target files do not already exist then tableName_* will expand either to itself or to nothing, depending on the current values of the shell options, but neither of these is useful to you.

In the third place, suppose you actually had the command

mv schema_tableName_1.sql schema_tableName_2.sql schema_tableName_3.sql \
          tableName_1.sql        tableName_2.sql        tableName_3.sql

or

mv schema_tableName_1.sql tableName_1.sql \
   schema_tableName_2.sql tableName_2.sql \
   schema_tableName_3.sql tableName_3.sql

or something that would expand to one of those. It seems like you're going for something like that, but mv doesn't do what you want with those. It does not perform pairwise moves, other than when given only a single pair of non-option arguments. When more than two non-option arguments are presented to it, the last must name a directory, and the files named by all the others are moved into that directory.<sup>*</sup>

To perform pairwise moves, you need a mv command for each pair. A shell for loop seems natural for this. And you need somehow to generate the destination filename from the source filename. The shell has transformative parameter expansion options that are well suited to this. Overall:

for f in schema_tableName_*.sql; do
  mv &quot;${f}&quot; &quot;${f#schema_}&quot;
done

That expands the glob schema_tableName_*.sql and for each resulting filename in turn, sets shell variable f to the filename and executes the commands between do and done. The &quot;${f#schema_}&quot; expands to the value of variable f with the prefix "schema_" removed, if present. That gives you exactly the pairwise mv commands you want.

Additionally, since you tagged Linux, you consider using the rename command. This performs potentially many file renamings based on string substitution, so it can afford a slightly simpler command, but it is specific to Linux:

rename schema_ &#39;&#39; schema_tableName_*.sql

I generally recommend preferring standard commands such as mv over platform-specific ones such as rename, as that develops skills that are more broadly reusable (to MacOS, for example), but YMMV.


<sup>*</sup>Or you can specify a target directory via the -t option, but the destination must in any case be a directory.

答案2

得分: 0

你尝试过使用 rename 命令进行批量重命名 Linux 命令吗?

或者你可以创建一个 Bash 脚本,循环匹配给定的模式并替换为另一个,类似于:

orig=schema_tableName_
dest=tableName_

for ((i=0; i<(ls ${orig}*|wc -l); i++)) {
  cp ${orig} ${dest} -v
}

还有其他选项:https://www.makeuseof.com/batch-rename-files-in-linux/

英文:

Have you tried rename for batch renaming linux command ?

Or you can create a bash script that loop for a giver pattern and replace to another something like:

orig=schema_tableName_
dest=tableName_

for(i=0; i&lt;(ls ${orig}*|wc -l); i++) {
  cp ${orig} ${dest} -v
}

there are other options: https://www.makeuseof.com/batch-rename-files-in-linux/

huangapple
  • 本文由 发表于 2023年6月22日 19:33:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76531443.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定