What Does .size mean - ruby

What does target.size mean in the below code and what does w mean that is next to the filename? And when I remove w or .size the program what does that mean?
filename = ARGV.first
script = $0
puts "We're going to erase #{filename}."
puts "If you don't wnat that, hit CTRL-C (^C)."
puts "If you do want that, hit RETURN."
print "? "
STDIN.gets
puts "Opening the file..."
target = File.open(filename,'w')
puts "Truncating the file. Goodbye!"
target.truncate(target.size)
puts "Now I'm going to ask you for three lines."
print "line 1: "; line1 = STDIN.gets.chomp()
print "line 2: "; line2 = STDIN.gets.chomp()
print "line 3: "; line3 = STDIN.gets.chomp()
puts "I'm going to write these to the file"
target.write(line1)
target.write("\n")
target.write(line2)
target.write("\n")
target.write(line3)
target.write("\n")
puts "And finally, we Close it"
target.close()

File.open(filename,'w') gives you a File object, which is assigned to the local variable target.target.size means actually File#size, which Returns the size of file in bytes. If you don't supply the mode as 'w', then the file will be opened with mode 'r', which is a default mode.
Read IO Open Mode :
"w" :
Write-only, truncates existing file to zero length or creates a new file for writing.
Explanation of the line target.truncate(target.size).
Here you actually called File#truncate, what this method does is Truncates file to at most integer bytes. That means you are deleting the file contents fully and making the file size as zero.

Related

rename files with Ruby

I'm trying this script to rename a series of files with unwanted characters:
$stdout.sync
print "Enter the file search query: "; search = gets.chomp
print "Enter the target to replace: "; target = gets.chomp
print " Enter the new target name: "; replace = gets.chomp
Dir['*'].each do |file|
# Skip directories
next unless File.file?(file)
old_name = File.basename(file,'.*')
if old_name.include?(search)
# Are you sure you want gsub here, and not sub?
# Don't use `old_name` here, it doesn't have the extension
new_name = File.basename(file).gsub(target,replace)
File.rename( file, new_path )
puts "Renamed #{file} to #{new_name}" if $DEBUG
end
end
I would like to be able to pass as a prompt argument the path of the directory that contains the files to be renamed, and then I modified the script as follows:
$stdout.sync
path = ARGV[0]
print "Enter the file search query: "; search = gets.chomp
print "Enter the target to replace: "; target = gets.chomp
print " Enter the new target name: "; replace = gets.chomp
Dir[path].each do |file|
# Skip directories
next unless File.file?(file)
old_name = File.basename(file,'.*')
if old_name.include?(search)
# Are you sure you want gsub here, and not sub?
# Don't use `old_name` here, it doesn't have the extension
new_name = File.basename(file).gsub(target,replace)
File.rename( file, new_path )
puts "Renamed #{file} to #{new_name}" if $DEBUG
end
end
get this error message:
renamefiles.rb:3:in `gets': Is a directory # io_fillbuf - fd:7
why?
When you pass an argument such that ARGV is populated the ruby interpreter will assume you mean Kernel#gets which expects a filename.
You should be able to fix this by using STDIN.gets so you would have
print "Enter the file search query: "; search = STDIN.gets.chomp
print "Enter the target to replace: "; target = STDIN.gets.chomp
print " Enter the new target name: "; replace = STDIN.gets.chomp
I have refined the code so that the file extension is not changed, and the directories are also renamed.
I have two problems left to solve:
-the passage of the path from argv (the path is not correctly recognized)
-I would like to recursively rename, even files in directories
path = ARGV[0]
print "Enter the file search query: "; search = gets.chomp
print "Enter the target to replace: "; target = gets.chomp
print " Enter the new target name: "; replace = gets.chomp
Dir::chdir('/Users/dennis/Documents/test/daRinominare')
Dir['*'].each do |file|
#puts file
if Dir.exist?(file)
directoryList = file
old_name = File.basename(file)
new_name = old_name.gsub(target,replace)
File.rename( file, new_name)
end
next unless File.file?(file)
old_name = File.basename(file,'.*')
extension = File.extname(file)
if old_name.include?(search)
new_name = old_name.gsub(target,replace) + extension
File.rename( file, new_name)
puts "Renamed #{file} to #{new_name}" if $DEBUG
end
end
Kernel.gets reads from ARGF, which acts as an aggregate IO to read from the files named in ARGV, unless ARGV is empty in which case ARGF reads from $stdin. ARGF.gets will generate errors like EISDIR and ENOENT if ARGV has entries which are paths to directories or paths that don't exist.
If you want to read user input, use $stdin.gets
(The difference between $stdin and STDIN: The constant STDIN is the process standard input stream, and is the initial value of the variable $stdin which can be reassigned to change the source used by library methods; see globals. I use $stdin unless I need to change $stdin and also use STDIN for another purpose.)

File.exist? always returns false even when file does exist

I have a program that tries to open a file:
Dir.chdir(File.dirname(__FILE__))
puts "Enter file name: ";
relPath = gets;
absPath = Dir.pwd << "/" << relPath;
if File.exist?(absPath) then
puts "File exists";
file = File.open(absPath, "r");
other code...
else
puts "File does not exist";
end
It always prints "File does not exist" even when the current directory exists and the file also exists. The file and script are in the same directory.
I am running it on Mac OS X Yosemite (10.10.3) and Ruby 2.2.0p0.
I can't explain why (albeit I have strong belief that it's for some whitespace characters) but with this little contribution it works ok.
Dir.chdir(File.dirname(__FILE__))
print "Enter file name:";
relPath = gets.chomp; #intuitively used this, and it wroked fine
absPath = File.expand_path(relPath) #used builtin function expand_path instead of string concatenation
puts absPath
puts File.file?(absPath)
if File.exist?(absPath) then
puts "File exists";
puts File.ctime(absPath) #attempting a dummy operation :)
else
puts "File does not exist";
end
runnning code
$ ls -a anal*
analyzer.rb
$ ruby -v
ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-linux]
ziya#ziya:~/Desktop/code/ruby$ ruby fileexists.rb
Enter file name:analyzer.rb
/home/ziya/Desktop/code/ruby/analyzer.rb #as a result of puts absPath
true #File.file?(absPath) => true
File exists
2015-06-11 12:48:31 +0500
That code has syntax error ("if" doesnt need "then"), and you dont have to put ";" after each line.
try
Dir.chdir(File.dirname(__FILE__))
puts "Enter file name: "
relPath = gets
absPath = "#{Dir.pwd}/#{relPath.chop}"
if File.exist?(absPath)
puts "File exists"
file = File.open(absPath, "r")
else
puts "File does not exist"
end
remember that gets will add a new line character so you will need to do a chomp, and that way to concatenate string won't work on ruby.
Your code is not idiomatic Ruby. I'd write it something like this untested code:
Dir.chdir(File.dirname(__FILE__))
puts 'Enter file name: '
rel_path = gets.chomp
abs_path = File.absolute_path(rel_path)
if File.exist?(abs_path)
puts 'File exists'
File.foreach(abs_path) do |line|
# process the line
end
else
puts 'File does not exist'
end
While Ruby supports the use of ;, they're for use when we absolutely must provide multiple commands on one line. The ONLY time I can think of needing that is when using Ruby to execute single-line commands at the command-line. In normal scripts I've never needed ; between statements.
then is used with if when we're using a single line if expression, however, we have trailing if which removes the need for then. For instance, these accomplish the same thing but the second is idiomatic, shorter, less verbose and easier to read:
if true then a = 1 end
a = 1 if true
See "What is the difference between "if" statements with "then" at the end?" for more information.
Instead of relPath and absPath we use snake_case for variables, so use rel_path and abs_path. It_is_a_readability AndMaintenanceThing.
File.absolute_path(rel_path) is a good way to take the starting directory and return the absolute path given a relative directory.
File.foreach is a very fast way to read a file, faster than slurping it using something like File.read. It is also scalable whereas File.read is not.

File Shows error

while inserting the content to a file:
file1=File.new("output.txt","w+")
puts "enter the string"
in1=gets.chomp
if file1
file1.syswrite()
else
puts cant write
end
file1.close
Try this, it uses the write method on the File class. Remember when you're writing a puts statement, the succeeding String needs to be in quotes.
file1=File.new("output.txt","w+")
puts "enter the string"
in1=gets.chomp
if file1
file1.write(in1)
else
puts "can't write"
end
file1.close

How to stop Ruby automatically adding carriage returns

I am having problems constructing text files from a Windows machine to be read on a Linux environment.
def test
my_file = Tempfile.new('filetemp.txt')
my_file.print "This is on the first line"
my_file.print "\x0A"
my_file.print "This is on the second line"
my_file.close
FileUtils.mv(my_file.path, "C:/Users/me/Desktop/Folder/test.usr")
end
0Ais the ASCII code for line feed, yet when I open the resulting file in Notepad++, I see it has appended CR and LF on the end of the line.
How do I add only a Line Feed as the new line character?
try setting the output separator $\ to \n.
def test
$\ = "\n"
my_file = Tempfile.new('filetemp.txt')
my_file.print "This is on the first line"
my_file.print "This is on the second line"
my_file.close
FileUtils.mv(my_file.path, "C:/Users/me/Desktop/Folder/test.usr")
end
or you should be able to use #write which will not add the output separator
def test
my_file = Tempfile.new('filetemp.txt')
my_file.write "This is on the first line"
my_file.write "\x0A"
my_file.write "This is on the second line"
my_file.close
FileUtils.mv(my_file.path, "C:/Users/me/Desktop/Folder/test.usr")
end
Opening the file in binary mode causes Ruby to 'suppress EOL <-> CRLF conversion on Windows' (see here).
The problem is that Tempfiles are automatically opened in w+ mode. I couldn't find a way to change this on creation of the Tempfile.
The answer is to change it after creation using binmode:
def test
my_file = Tempfile.new('filetemp.txt')
my_file.binmode
my_file.print "This is on the first line"
my_file.print "\x0A" # \n now also works as a newline character
my_file.print "This is on the second line"
my_file.close
FileUtils.mv(my_file.path, "C:/Users/me/Desktop/Folder/test.usr")
end

Ruby - 'read': can't convert String into Integer

New to Ruby, and programming in general.
I am trying to write to a file and then print what I wrote to the file in the terminal.
filename = ARGV.first
script = $0
puts "Would you like to read the file?"
puts "If you want to, hit RETURN."
puts "If you don't want to, hit CTRL+C."
prompt = "? "
STDIN.gets
puts "Opening file..."
target = File.open(filename, 'w+')
puts "Reading file..."
puts target.read()
puts "Blank, huh?"
print "Write something: "; line1 = STDIN.gets()
print "A little more: "; line2 = STDIN.gets()
target.write(line1)
target.write(line2)
puts "Let's read it now."
puts target.read()
The code runs until I get to the last line, at which time the following error is thrown:
exl16_2.rb:26:in `read': can't convert String into Integer (TypeError)
from exl16_2.rb:26:in `<main>'
Not sure what this means within the context of what I am trying to do (print out what was written).
Not sure what's causing the error on your side, what Ruby version are you using? I tried w/1.9 and 2.1 and didn't get that. There are however issues with your code, try this:
filename = ARGV.first
script = $0
puts "Would you like to read the file?"
puts "If you want to, hit RETURN."
puts "If you don't want to, hit CTRL+C."
prompt = "? "
STDIN.gets
puts "Opening file..."
target = File.open(filename, 'w+')
puts "Reading file..."
puts target.read()
puts "Blank, huh?"
print "Write something: "; line1 = STDIN.gets()
print "A little more: "; line2 = STDIN.gets()
target.write(line1)
target.write(line2)
target.rewind()
puts "Let's read it now."
puts target.read()
If you read from the file after you wrote it, it will appear empty. The rewind call will make sure you're reading from the beginning of the file.

Resources