英文:
How can move the file and change the file extension with simple bash?
问题
在我的当前目录中选择包含`sqlite`的文件:
ls | grep sqlite
null and empty string in sqlite.txt
pythoin write None into sqlite.txt
将它们移动到`/tmp`目录:
ls |grep sqlite |xargs -i mv {} /tmp
ls /tmp | grep sqlite
null and empty string in sqlite.txt
pythoin write None into sqlite.txt
如何将它们移动到`/tmp`并同时将文件扩展名更改为`rst`?
ls |grep sqlite | some_simple_bash_command
执行后:
ls /tmp | grep sqlite
null and empty string in sqlite.rst
pythoin write None into sqlite.rst
@David C. Rankin,`grep sqlite *`根本无法工作!
英文:
Select file which contains sqlite
in my current directory:
ls | grep sqlite
null and empty string in sqlite.txt
pythoin write None into sqlite.txt
Move them into /tmp
directory:
ls |grep sqlite |xargs -i mv {} /tmp
ls /tmp | grep sqlite
null and empty string in sqlite.txt
pythoin write None into sqlite.txt
How can move them into /tmp
and change the file extension as rst
at the same time?
ls |grep sqlite | some_simple_bash_command
After executing it:
ls /tmp | grep sqlite
null and empty string in sqlite.rst
pythoin write None into sqlite.rst
@David C. Rankin,grep sqlite *
can't work at all!
答案1
得分: 1
尝试这个 Shellcheck- 清理的代码:
for f in *sqlite*; do
mv -v -- ""$f"" ""/tmp/${f%.*}.rst""
done
*sqlite*
展开为当前目录中文件名中包含字符串sqlite
的文件列表。参见 Pattern Matching 部分的 Bash 参考手册。${f%.*}
展开为$f
的值,去除任何后缀。参见 删除字符串的一部分 (BashFAQ/100 (我如何在 bash 中进行字符串操作?))。--
是传递给mv
的参数,以确保正确处理文件名以-
开头的文件。参见 Bash 陷阱 #2 (cp $file $target)。
英文:
Try this Shellcheck-clean code:
for f in *sqlite*; do
mv -v -- "$f" "/tmp/${f%.*}.rst"
done
*sqlite*
expands to the list of files in the current directory that contain the stringsqlite
anywhere in their names. See the Pattern Matching section of the Bash Reference Manual.${f%.*}
expands to the value of$f
with any suffix removed. See Removing part of a string (BashFAQ/100 (How do I do string manipulation in bash?)).- The
--
argument tomv
is to ensure proper handling of files whose names begin with-
. See Bash Pitfalls #2 (cp $file $target).
答案2
得分: 0
这是您要翻译的文本:
"Let's expand on the comment a bit. First, learn not to pipe ls
to the utility you want to use. All utilities that operate on files will accept a list of filenames through file-globbing. So to grep
all files in the present working directory containing "sqlite"
it's just:
$ grep 'sqlite' *
To change a filename extension POSIX provides a parameter expansion with substring removal that allows you to trim from the right, e.g. ${var%pattern}
, to trim to the last occurrence of pattern
beginning from the right it is ${var%%pattern}
. Note: pattern
can contain normal file-globbing such as ?
or *
.
To trim from the left it is ${var#pattern}
and ${var##pattern}
, respectively. These are POSIX expansions meaning they are available in all POSIX shells. Bash on the other hand provides many, many more expansions (stuff between ${...}
) that only work in bash (referred to as "bashisms"
) Use POSIX when available to solve your problem for maximum portability.
To change the extension of a filename stored in the variable "$f"
, it would be:
mv "$f" "${f%.old}.new"`
Where old
and new
are the old and new file extensions.
When you want to rename or move and rename all files that result from a glob selection (e.g. using pattern*
or the like, a for
loop is what you need, e.g to select all files in the current directory whose name begins with pattern
you can use pattern*
in
for f in pattern*; do
printf "%s\n" "$f"
done
(which simply prints the filename)
To move all files beginning with pattern
to the /tmp
directory, it would be:
for f in pattern*; do
mv "$f" /tmp
done
(note: xargs
would do just fine here)
When you want to process files that are the result of running some other process or utility, bash provides process substitution allowing you to feed a while
loop in the form of while read -r var; do #stuff with "$var"; done < <(process)
. In your example of grep sqlite
to move all files returned to /tmp
while changing the extension from old
to new
, that would be:
while read -r f; do
mv "$f" "/tmp/${f%.old}.new"
done < <(grep 'sqlite' *)
(for POSIX shells you would pipe the result of grep
to your while
loop, e.g. grep 'sqlite' * | while read -r f ...
)
Look things over and let me know if you have questions or if I missed the intent of your question."
英文:
Let's expand on the comment a bit. First, learn not to pipe ls
to the utility you want to use. All utilities that operate on files will accept a list of filenames through file-globbing. So to grep
all files in the present working directory containing "sqlite"
it's just:
$ grep 'sqlite' *
To change a filename extension POSIX provides a parameter expansion with substring removal that allows you to trim from the right, e.g. ${var%pattern}
, to trim to the last occurrence of pattern
beginning from the right it is ${var%%pattern}
. Note: pattern
can contain normal file-globbing such as ?
or *
.
To trim from the left it is ${var#pattern}
and ${var##pattern}
, respectively. These are POSIX expansions meaning they are available in all POSIX shells. Bash on the other hand provides many, many more expansions (stuff between ${...}
) that only work in bash (referred to as "bashisms"
) Use POSIX when available to solve your problem for maximum portability.
To change the extension of a filename stored in the variable "$f"
, it would be:
mv "$f" "${f%.old}.new"`
Where old
and new
are the old and new file extensions.
When you want to rename or move and rename all files that result from a glob selection (e.g. using pattern*
or the like, a for
loop is what you need, e.g to select all files in the current directory whose name begins with pattern
you can use pattern*
in
for f in pattern*; do
printf "%s\n" "$f"
done
(which simply prints the filename)
To move all files beginning with pattern
to the /tmp
directory, it would be:
for f in pattern*; do
mv "$f" /tmp
done
(note: xargs
would do just fine here)
When you want to process files that are the result of running some other process or utility, bash provides process substitution allowing you to feed a while
loop in the form of while read -r var; do #stuff with "$var"; done < <(process)
. In your example of grep sqlite
to move all files returned to /tmp
while changing the extension from old
to new
, that would be:
while read -r f; do
mv "$f" "/tmp/${f%.old}.new"
done < <(grep 'sqlite' *)
(for POSIX shells you would pipe the result of grep
to your while
loop, e.g. grep 'sqlite' * | while read -r f ...
)
Look things over and let me know if you have questions or if I missed the intent of your question.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论