Finding all image files in folder and change their names with number - file

Let's assume we have following files.
00043.jpg
00086.jpg
00123.jpg
...
04523.jpg
What I want is, change their names to as following.
00001.jpg
00002.jpg
00003.jpg
so on
How can I do this on linux console?
Or I can use python scripts.

Supply the valid folder path and Run this code.
import os
# Function to rename multiple files
def main():
i = 0
path = 'E:\\files\\'
for filename in os.listdir("E:\\files"):
dst = str(i).zfill(4) + ".jpg"
src = path + filename
dst = path + dst
# rename() function will
# rename all the files
os.rename(src, dst)
i += 1
# Driver Code
if __name__ == '__main__':
# Calling main() function
main()

If you have PHP in your console,
<?php
$images = glob("*.jpg");
$start=0;
function squencer()
{
global $start;
++$start;
return str_pad($start, 5, "0", STR_PAD_LEFT);
}
foreach($images as $image)
{
$newname = squencer().".jpg";
rename($image, $newname);
}
Then run: php -f rename.php

The only standard command for renaming files is mv and it has very limited capability. What you want to do inherently requires a script because the complexity of sequential naming is beyond the capability of globbing or even regular expressions. You have not specified whether there are other files in the directory or whether you care about the original order. Unlike Windows, Linux directory contents are not in any predictable order. I assume that you do want to maintain the original order. Your example indicates 0-padding. This is an important detail. It means that a lexical sort matches what we intuitively think, e.g. that 43 > 42. Lexically, 43 > 42 but 42 > 043. I'm going to show you how to do this using Python, assuming that the directory contains other files and that you want to maintain the original order. The first line is a shebang, telling the OS to use python3. This is particularly for Ubuntu but most systems will need this or a variation of it because they use python 2 by default. Also, although Python doesn't care what kind of line endings are in the script, the OS itself reads the shebang and it requires that these be Unix.
#!/usr/bin/env python3
import os
jpgfiles = [f for f in os.listdir() if os.path.splitext(f)[1].casefold() == jpg']
jpgfiles.sort()
for i,f in enumerate(jpgfiles) :
os.rename(f, '%04.d' % i + '.jpg')
Python's inherent power enables a simple script like this to perform rather complex operations. But you don't want to have to write a script for every kind of file renaming you might want to do. When I couldn't find an existing program for the variety of renaming that I do, I wrote a Python program that can do what you want and much more. It is rene.py. You can get it at Sourceforge https://rene-file-renamer.sourceforge.io. It is free and open source (GNU GPL v3.0). The command to do what you want is rene *.jpg :.jpg I///5.

Related

Get all the functions' names from c/cpp files

For example, there is a C file a.c, there are three functions in this file: funA(), funB() and funC().
I want to get all the function names from this file.
Additionally, I also want to get the start line number and end line number of each function.
Is there any solution?
Can I use clang to implement it?
You can compile the file and use nm http://en.wikipedia.org/wiki/Nm_(Unix) on the generated binary. You can then just parse the output of nm to get the function names.
If you want to get line numbers, you can use the function names to parse the source file for line numbers.
All the this can be accomplished with a short perl script that makes system calls to gcc and nm.
This is assuming you are using a *nix system of course...
One solution that works well for the job is cproto. It will scan source files (in K&R or ANSI-C format) and output the function prototypes. You can process entire directories of source files with a find command similar to:
find "$dirname" -type f -name "*.c" \
-exec /path/to/cproto -s \
-I/path/to/extra/includes '{}' >> "$outputfile" \;
While the cproto project is no longer actively developed, the cproto application continues to work very, very well. It provides function output in a reasonable form that can be fairly easily parsed/formatted as you desire.
Note: this is just one option based on my use. There are many others available.

How to extract data from multiple files with Python?

I am new to Python, which is also my first programming language. I have a set of txt files (academic papers), I need to extract the paper ID (e.g. ID: a1111111) and abstract (e.g. ABSTRACT: .....). I have no idea how to extract this data from multiple files from multiple folders? Thanks A LOT!
So your question is two part: reading files and accessing folders
Reading files
The methods/objects in python used for reading files is in Python's documentation on chapter 7:
http://docs.python.org/2/tutorial/inputoutput.html
The basic gist is that you use the open method to access files that are in the same directory
f = open('stuff.txt', 'r')
Where stuff.txt is the name of the file in the same directory that your python file is in.
Calling print f.read() will display the text (in String format) of the file. Feel free to assign f.read() to a variable to capture the data.
>>> x = f.read()
>>> print x
This is the entire file.\n
Best read the documentation for all these methods, cause there are subtleties. For example, calling f.read() once will return the entire file contents to you, but calling f.read() again will return an empty string, as the "end of the file has been reached."
Accessing Folders
Can you explain to me how exactly you'd like to access folders? In this case, it would be much easier to just put all your files in the same directory as where you are running your python file.
However, the basic way to move around in python is to use: os.chdir(path) which is basically cd'ing around. You must import os before you use this.
Leave a comment if you'd like some more information

How do I add an operator to Bash in Linux?

I'd like to add an operator ( e.g. ^> ) to handle prepend instead append (>>). Do I need to modify Bash source or is there an easier way (plugin, etc)?
First of all, you'd need to modify bash sources and quite heavily. Because, above all, your ^> would be really hard to implement.
Note that bash redirection operators usually do a very simple writes, and work on a single file (or program in case of pipes) only. Excluding very specific solutions, you usually can't write to a beginning of a file for the very simple reason you'd need to move all remaining contents forward after each write. You could try doing that but it will be hard, very ineffective (since every write will require re-writing the whole file) and very unsafe (since with any error you will end up with random mix of old and new version).
That said, you are indeed probably better off with a function or any other solution which would use a temporary file, like others suggested.
For completeness, my own implementation of that:
prepend() {
local tmp=$(tempfile)
if cat - "${1}" > "${tmp}"; then
mv "${tmp}" "${1}"
else
rm -f "${tmp}"
# some error reporting
fi
}
Note that you unlike #jpa suggested, you should be writing the concatenated data to a temporary file as that operation can fail and if it does, you don't want to lose your original file. Afterwards, you just replace the old file with new one, or delete the temporary file and handle the failure any way you like.
Synopsis the same as with the other solution:
echo test | prepend file.txt
And a bit modified version to retain permissions and play safe with symlinks (if that is necessary) like >> does:
prepend() {
local tmp=$(tempfile)
if cat - "${1}" > "${tmp}"; then
cat "${tmp}" > "${1}"
rm -f "${tmp}"
else
rm -f "${tmp}"
# some error reporting
fi
}
Just note that this version is actually less safe since if during second cat something else will write to disk and fill it up, you'll end up with incomplete file.
To be honest, I wouldn't personally use it but handle symlinks and resetting permissions externally, if necessary.
^ is a poor choice of character, as it is already used in history substitution.
To add a new redirection type to the shell grammar, start in parse.y. Declare it as a new %token so that it may be used, add it to STRING_INT_ALIST other_token_alist[] so that it may appear in output (such as error messages), update the redirection rule in the parser, and update the lexer to emit this token upon encountering the appropriate characters.
command.h contains enum r_instruction of redirection types, which will need to be extended. There's a giant switch statement in make_redirection in make_cmd.c processing redirection instructions, and the actual redirection is performed by functions throughout redir.c. Scattered throughout the rest of source code are various functions for printing, copying, and destroying pipelines, which may also need to be updated.
That's all! Bash isn't really that complex.
This doesn't discuss how to implement a prepending redirection, which will be difficult as the UNIX file API only provides for appending and overwriting. The only way to prepend to a file is to rewrite it entirely, which (as other answers mention) is significantly more complex than any existing shell redirections.
Might be quite difficult to add an operator, but perhaps a function could be enough?
function prepend { tmp=`tempfile`; cp $1 $tmp; cat - $tmp > $1; rm $tmp; }
Example use:
echo foobar | prepend file.txt
prepends the text "foobar" to file.txt.
I think bash's plugin architecture (loading shared objects via the 'enable' built-in command) is limited to providing additional built-in commands. The redirection operators are part of they syntax for running simple commands, so I think you would need to modify the parser to recognize and handle your new ^> operator.
Most Linux filesystems do not support prepending. In fact, I don't know of any one that has a stable userspace interface for it. So, as stated by others already, you can only rely on overwriting, either just the initial parts, or the entire file, depending on your needs.
You can easily (partially) overwrite initial file contents in Bash, without truncating the file:
exec {fd}<>"$filename"
printf 'New initial contents' >$fd
exec {fd}>&-
Above, $fd is the file descriptor automatically allocated by Bash, and $filename is the name of the target file. Bash opens a new read-write file descriptor to the target file on the first line; this does not truncate the file. The second line overwrites the initial part of the file. The position in the file advances, so you can use multiple commands to overwrite consecutive parts in the file. The third line closes the descriptor; since there is only a limited number available to each process, you want to close them after you no longer need them, or a long-running script might run out.
Please note that > does less than you expected:
Remove the > and the following word from the commandline, remembering the redirection.
When the commandline is processed and the command can be launched, calling fork(2) (or clone(2)), to create a new process.
Modify the new process according to the command. That includes things like modified environment variables (SOMEVAR=foo yourcommand), but also changed filedescriptors. At this point, a > yourfile from the cmdline will have the effect that the file is open(2)'ed at the stdout filedescriptor (that is #1) in write-only mode truncating the file to zero bytes. A >> yourfile would have the effect that the file is oppend at stdout in write-only mode and append mode.
(Only now launch the program, like execv(yourprogram, yourargs)
The redirections could, for a simple example, be implemented like
open(yourfile, O_WRONLY|O_TRUNC);
or
open(yourfile, O_WRONLY|O_APPEND);
respectively.
The program then launched will have the correct environment set up, and can happily write to fd1. From here, the shell is not involved. The real work is not done by the shell, but by the operating system. As Unix doesn't have a prepend mode (and it would be impossible to integrate that feature correctly), everything you could try would end up in a very lousy hack.
Try to re-think your requirements, there's always a simpler way around.

Tcl determine file name from browser upload

I have run into a problem in one of my Tcl scripts where I am uploading a file from a Windows computer to a Unix server. I would like to get just the original file name from the Windows file and save the new file with the same name. The problem is that [file tail windows_file_name] does not work, it returns the whole file name like "c:\temp\dog.jpg" instead of just "dog.jpg". File tail works correctly on a Unix file name "/usr/tmp/dog.jpg", so for some reason it is not detecting that the file is in Windows format. However Tcl on my Windows computer works correctly for either name format. I am using Tcl 8.4.18, so maybe it is too old? Is there another trick to get it to split correctly?
Thanks
The problem here is that on Windows, both \ and / are valid path separators so long Windows API is concerned (even though only \ is deemed to be "official" on Windows). On the other hand, in POSIX, the only valid path separator is /, and the only two bytes which can't appear in a pathname component are / and \0 (a byte with value 0).
Hence, on a POSIX system, "C:\foo\bar.baz" is a perfectly valid short filename, and running
file normalize {C:\foo\bar.baz}
would yield /path/to/current/dir/C:\foo\bar.baz. By the same logic, [file tail $short_filename] is the same as $short_filename.
The solution is to either do what Glenn Jackman proposed or to somehow pass the short name from the browser via some other means (some JS bound to an appropriate file entry?). Also you could attempt to detect the user's OS from the User-Agent header.
To make Glenn's idea more agnostic to user's platform, you could go like this:
Scan the file name for "/".
If none found, do set fname [string map {\\ /} $fname] then go to the next step.
Use [file tail $fn] to extract the tail name.
It's not very bullet-proof, but supposedly better than nothing.
You could always do [lindex [split $windows_file_name \\] end]

Get containing path of lua file

I am wondering if there is a way of getting the path to the currently executing lua script file?
This is specifically not the current working directory, which could be entirely different. I know luafilesystem will let me get the current working directory, but it doesn't seem to be able to tell the current executing script file.
Thanks
EDIT:
I'm not running from the standard command line interpreter, I am executing the scripts from a C++ binary via luabind.
This is a more elegant way:
function script_path()
local str = debug.getinfo(2, "S").source:sub(2)
return str:match("(.*/)")
end
print(script_path())
If the Lua script is being run by the standard command line interpreter, then try arg[0].
Shortest form which I have found looks like this:
debug.getinfo(1).source:match("#?(.*/)")
Index 1, 2- other - depends on which function in call stack you want to query. 1 is last called function (where you're in). If you're running in global context, then probably 2 is more appropriate (haven't tested by myself)
As lhf says:
~ e$ echo "print(arg[0])" > test.lua
~ e$ lua test.lua
test.lua
~ e$ cd /
/ e$ lua ~/test.lua
/Users/e/test.lua
/ e$
Here's the same info using the debug.getinfo mechanism
~ e$ echo "function foo () print(debug.getinfo(1).source) end; foo()" > test.lua
~ e$ lua test.lua
#test.lua
~ e$ cd /
/ e$ lua ~/test.lua
#/Users/e/test.lua
/ e$
This is available from the C API lua_getinfo
The only reliable way to get what you want is to replace dofile with your own version of this function. Even the debug.getinfo method won't work, because it will only return the string passed to dofile. If that was a relative path, it has no idea how it was converted to an absolute path.
The overriding code would look something like this:
local function CreateDoFile()
local orgDoFile = dofile;
return function(filename)
if(filename) then --can be called with nil.
local pathToFile = extractFilePath(filename);
if(isRelativePath(pathToFile)) then
pathToFile = currentDir() .. "/" .. pathToFile;
end
--Store the path in a global, overwriting the previous value.
path = pathToFile;
end
return orgDoFile(filename); --proper tail call.
end
end
dofile = CreateDoFile(); //Override the old.
The functions extractFilePath, isRelativePath, and currentDir are not Lua functions; you will have to write them yourself. The extractFilePath function pulls a path string out of a filename. isRelativePath takes a path and returns whether the given path is a relative pathname. currentDir simply returns the current directory. Also, you will need to use "\" instead of "/" on Windows machines.
This function stores the path in a global called path. You can change that to whatever you like.
I have written a function getScriptDir which uses the debug information like a few other people have suggested, but this one is going to work everytime (at least in Windows). But the thing is there are quite a few lines of code as it uses another function string.cut which i have created, which separates a string every given pattern, and puts it into a table.
function string.cut(s,pattern)
if pattern == nil then pattern = " " end
local cutstring = {}
local i1 = 0
repeat
i2 = nil
local i2 = string.find(s,pattern,i1+1)
if i2 == nil then i2 = string.len(s)+1 end
table.insert(cutstring,string.sub(s,i1+1,i2-1))
i1 = i2
until i2 == string.len(s)+1
return cutstring
end
function getScriptDir(source)
if source == nil then
source = debug.getinfo(1).source
end
local pwd1 = (io.popen("echo %cd%"):read("*l")):gsub("\\","/")
local pwd2 = source:sub(2):gsub("\\","/")
local pwd = ""
if pwd2:sub(2,3) == ":/" then
pwd = pwd2:sub(1,pwd2:find("[^/]*%.lua")-1)
else
local path1 = string.cut(pwd1:sub(4),"/")
local path2 = string.cut(pwd2,"/")
for i = 1,#path2-1 do
if path2[i] == ".." then
table.remove(path1)
else
table.insert(path1,path2[i])
end
end
pwd = pwd1:sub(1,3)
for i = 1,#path1 do
pwd = pwd..path1[i].."/"
end
end
return pwd
end
Note: if you want to use this function in another OS than Windows, you have to change the io.popen("echo %cd%") in the line 15 to whatever command gives you present working directory in your OS, e.g. io.popen("pwd") for Linux, and the pwd2:sub(2,3) == ":/" in the line 18 to whatever represents the root directory in your OS, e.g. pwd2:sub(1,1) == "/" for Linux.
Note2: if you don't provide the source variable to the function via debug.getinfo(1).source when calling it, then it will return the path to the directory of the file containing this function. Therefore, if you want to get the directory of a file which you called via dofile or loadfile, you will have to give it the source, like this: getScriptDir(debug.getinfo(1).source).
Have a look at the Lua debug library, which is part of the standard Lua distribution. You can use debug.getinfo to find the current file, or the file up N frames on the call stack:
http://www.lua.org/manual/5.1/manual.html#5.9
Note that this is probably fairly slow, so it is not something you want to do on the fast path if you are worried about such things.
if you want the actual path :
path.dirname(path.abspath(debug.getinfo(1).short_src))
else use this for full file path :
path.abspath(debug.getinfo(1).short_src)
If you want the real path including the filename, just use the following
pathWithFilename=io.popen("cd"):read'*all'
print(pathWithFilename)
Tested on Windows.
Explanation:
io.popen - Sends commands to the command line, and returns the output.
"cd" - when you input this in cmd you get the current path as output.
:read'*all' - as io.popen returns a file-like object you can read it with the same kind of commands. This reads the whole output.
If someone requires the UNC path:
function GetUNCPath(path,filename)
local DriveLetter=io.popen("cd "..path.." && echo %CD:~0,2%"):read'*l'
local NetPath=io.popen("net use "..DriveLetter):read'*all'
local NetRoot=NetPath:match("[^\n]*[\n]%a*%s*([%a*%p*]*)")
local PathTMP=io.popen("cd "..path.." && cd"):read'*l'
PathTMP=PathTMP:sub(3,-1)
UNCPath=NetRoot..PathTMP.."\\"..filename
return UNCPath
end
arg[0]:match('.*\\')
If it returns nil try changing the .\*\\\ with .*/ and arg[0] with debug.getinfo(1).short_src.
But I find this to be the best and shortest way to get the current directory.
You can of course append the file you are looking for with the .. operator. It will look something like this:
arg[0]:match('.*\\')..'file.lua'
This version of anthonygore's answer is cross-platform (handles Windows backslash paths) and works when the script is run without a path (returns relative path).
local function script_path()
local str = debug.getinfo(2, "S").source:sub(2)
return str:match("(.*[/\\])") or "./"
end

Resources